Angular下H5上传图片的方法(可多张上传)


Posted in Javascript onJanuary 09, 2017

最近做的项目中用到了angular下上传图片功能,在做的过程中遇到了许多问题,最终都得以解决

angular上传时和普通上传时过程差不多,只不过是要不一些东西转化为angular的东西。

1.ng-file-select,指令angular是没此功能的,其实也是转化成了change事件,不多说,直接上代码

angular.module('myApp')
.directive('ngFileSelect', [ '$parse', '$timeout', function($parse, $timeout) {
    return function(scope, elem, attr) {
      var fn = $parse(attr['ngFileSelect']);
      elem.bind('change', function(evt) {
        var files = [], fileList, i;
        fileList = evt.target.files;
        if (fileList != null) {
          for (i = 0; i < fileList.length; i++) {
            files.push(fileList.item(i));
          }
        }
        $timeout(function() {
          fn(scope, {
            $files : files,
            $event : evt
          });
        });
      });
    };
  }])

2.服务 上传文件前预览并压缩图片功能

//上传文件预览
angular.module('myServers',[])
  .factory('fileReader', ['$q', '$log', function($q, $log) {
    var dataURItoBlob = function(dataURI) { 
      // convert base64/URLEncoded data component to raw binary data held in a string 
      var byteString; 
      if (dataURI.split(',')[0].indexOf('base64') >= 0) 
        byteString = atob(dataURI.split(',')[1]); 
      else 
        byteString = unescape(dataURI.split(',')[1]); 
      // separate out the mime component 
      var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0]; 
      // write the bytes of the string to a typed array 
      var ia = new Uint8Array(byteString.length); 
      for (var i = 0; i < byteString.length; i++) { 
        ia[i] = byteString.charCodeAt(i); 
      } 
      return new Blob([ia], { 
        type: mimeString 
      }); 
    }; 
    var onLoad = function(reader, deferred, scope,file) {
      return function() {
        scope.$apply(function() {
           var img = new Image();
          //前端压缩图片
          img.onload = function(){ 
            //resize the image using canvas 
            var canvas = document.createElement("canvas"); 
            var ctx = canvas.getContext("2d"); 
            var width = img.width; 
            var height = img.height; 
            var MAX_WIDTH = width>2500 ? width/2 : 2500; 
            var MAX_HEIGHT = height>2500 ? height/2 : 2500;
            if (width > height) { 
              if (width > MAX_WIDTH) { 
                height *= MAX_WIDTH / width; 
                width = MAX_WIDTH; 
              } 
            } else { 
              if (height > MAX_HEIGHT) { 
                width *= MAX_HEIGHT / height; 
                height = MAX_HEIGHT; 
              } 
            }
            canvas.width = width ; 
            canvas.height = height; 
            ctx.drawImage(img, 0, 0, width, height); 
            var dataURL = canvas.toDataURL('image/jpeg', 1);
            var blob = dataURItoBlob(dataURL); 
            if(blob.size > 2000 * 1024){
              dataURL = canvas.toDataURL('image/jpeg', .2);
            }else if(blob.size > 1000 * 1024){
              dataURL = canvas.toDataURL('image/jpeg', .5);
            }else{
              dataURL = canvas.toDataURL('image/jpeg', .8);
            }
            blob = dataURItoBlob(dataURL);
            deferred.resolve(blob);
          }
          img.src = URL.createObjectURL(file);
        });
      };
    };
    var onError = function(reader, deferred, scope) {
      return function() {
        scope.$apply(function() {
          deferred.reject(reader.result);
        });
      };
    };
    var onProgress = function(reader, scope) {
      return function(event) {
        scope.$broadcast("fileProgress", {
          total: event.total,
          loaded: event.loaded
        });
      };
    };
    var getReader = function(deferred, scope, file) {
      var reader = new FileReader();
      reader.onload = onLoad(reader, deferred, scope,file);
      reader.onerror = onError(reader, deferred, scope);
      reader.onprogress = onProgress(reader, scope);
      return reader;
    };
    var readAsDataURL = function(file, scope) {
      var deferred = $q.defer();
      var reader = getReader(deferred, scope,file);
      reader.readAsDataURL(file);
      return deferred.promise;
    };
    return {
      readAsDataUrl: readAsDataURL
    };
  }]);

这里说明一下,部分代码是参考别人的代码(http://blog.csdn.net/zx007fack/article/details/41073601),但是对其中内容做了修改,因为用原来的代码,如果不加前端压缩功能是正常的,前端压缩的话因为要用到canvas, 直接用reader.result在ios上图片的宽高拿到的直接是0,android上是可以的,具体原因不是很确定是不是base64的问题,所以我又直接把file传了进来,然后用原生js的方法新建图片元素拿到宽高,再用Canvas进行压缩,最后转成blob,通过formData传给后台。

3.controller代码

//选择图片后执行的方法
    $scope.fileArr = [];
    $scope.imgSrcArr = [];var i = 0; //为ios上图片都为image时添加序号
    $rootScope.onFileSelect = function(files, event) {
      //预览上传图片开始
      $rootScope.startLoading();
      var $this = angular.element(event.target);
      angular.forEach(files, function(value, index) {
        var fileIn = value;
        var fileInName = fileIn.name;
        var fileType = fileInName.substring(fileInName.lastIndexOf(".") + 1, fileInName.length);
        //解决ios下所有图片都为image.jpg的bug
        if(fileIn) {
          fileInName = fileInName.split('.')[0] + i + '.' + fileType;
          i++;
        }
        attachvo.push({
          name: fileInName,
          type: fileType
        });
        fileReader.readAsDataUrl(fileIn, $scope)
          .then(function(result) {
            result.name = fileInName;
            $scope.fileArr.push(result);
            $scope.imgSrcArr.push(URL.createObjectURL(result));






//每次上传后清空file框,确保每次都能调用change事件
            document.querySelector('.upload').reset();
          });
        $scope.$on('fileProgress', function(event, data) {
          if(data.total == data.loaded) {
            $timeout(function() {
              //上传图片结束
              $rootScope.endLoading();
            }, 200)
          }
        });      
      });
      $rootScope.showAttachment = false;
    };return false;
    }

这里处理了下图片,在名字上加了序号,因为在ios上每次选择的图片名字都叫image,查找了很多资料,说是safari的bug,后面版本才会解决,暂时只能以这种方式解决了。循环是上传多张图片

3.html代码

<ul class="upload-view-ul">
    <li ng-repeat="src in imgSrcArr" class="pull-left" ng-click="delCurUpload(src)" 
      ng-class="{'row-last': (($index+1) % 5==0)}">
      <span>x</span>
      <em ng-if='nrc'>{{formData.attachvo[$index].attachmentType}}</em>
      <img ng-src="{{src}}">
    </li>
    <div class="attachment" pop-type-select ng-if="nrc">+</div>
    <div class="attachment" ng-if="!nrc">
      +
      <form class="upload">
        <input type="file" name="file[]" ng-file-select="onFileSelect($files, $event)" multiple>
      </form>
    </div>
  </ul>

4.顺便把formdata时代码贴一下,采用H5上传图片的方式

this.FormdataPost = function(pathUrl, formId, formData, files) {
    var fd = new FormData();
    fd.append('formId', formId);
    if(files && angular.isArray(files)) {
      files.forEach(function(item) {
        fd.append('file', item, item.name);
      });
    }
    fd.append('formData', angular.toJson(formData, true));
    var httpConfig = {
      headers: {
        'Authorization': 'Bearer ' + this.token,
        'Content-Type': undefined
      },
      transformRequest: angular.identity
    };
    return $http.post(rootUrl + pathUrl, fd, httpConfig).then(function(data) {
      return data;
    }).catch(function(error) {
      $rootScope.interfaceName = pathUrl;
      $rootScope.setNewWortStatus({
        status: error.status,
        errInfo: error.data && error.data.statusInfo || ''
      });
      return error;
    });
  }

思路有一点混乱,不知道讲清楚了没有,想起来再添加吧

以上所述是小编给大家介绍的Angular下H5上传图片的方法(可多张上传),希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
dojo 之基础篇(二)之从服务器读取数据
Mar 24 Javascript
基于jquery的不规则矩形的排列实现代码
Apr 16 Javascript
js自定义事件及事件交互原理概述(二)
Feb 01 Javascript
jQuery中校验时间格式的正则表达式小结
Sep 22 Javascript
Js和JQuery获取鼠标指针坐标的实现代码分享
May 25 Javascript
js的各种排序算法实现(总结)
Jul 23 Javascript
微信小程序技巧之show内容展示,上传文件编码问题
Jan 23 Javascript
Angular.JS内置服务$http对数据库的增删改使用教程
May 07 Javascript
JS实现简单的点赞与踩功能示例
Dec 05 Javascript
一秒学会微信小程序制作table表格
Feb 14 Javascript
微信小程序scroll-view实现滚动到锚点左侧导航栏点餐功能(点击种类,滚动到锚点)
Jun 11 Javascript
原生js实现拖拽移动与缩放效果
Aug 24 Javascript
详解网站中图片日常使用以及优化手法
Jan 09 #Javascript
jQuery实现表格元素动态创建功能
Jan 09 #Javascript
input输入密码变黑点密文的实现方法
Jan 09 #Javascript
微信小程序 css使用技巧总结
Jan 09 #Javascript
详解Jquery Easyui的验证扩展
Jan 09 #Javascript
Javascript blur与click冲突解决办法
Jan 09 #Javascript
简单实现jQuery级联菜单
Jan 09 #Javascript
You might like
什么是调频(FM)、调幅(AM)、短波(SW)、长波(LW)
2021/03/01 无线电
Laravel中基于Artisan View扩展包创建及删除应用视图文件的方法
2016/10/08 PHP
PHP函数rtrim()使用中的怪异现象分析
2017/02/24 PHP
yii2.0整合阿里云oss删除单个文件的方法
2017/09/19 PHP
Thinkphp5框架简单实现钩子(Hook)行为的方法示例
2019/09/03 PHP
laravel 解决Validator使用中出现的问题
2019/10/25 PHP
JavaScript DOM 学习第七章 表单的扩展
2010/02/19 Javascript
JavaScript 嵌套函数指向this对象错误的解决方法
2010/03/15 Javascript
javascript 仿QQ滑动菜单效果代码
2010/09/03 Javascript
基于jQuery的可用于选项卡及幻灯的切换插件
2011/03/28 Javascript
关于 文本框默认值 的操作js代码
2012/01/12 Javascript
[JSF]使用DataModel处理表行事件的实例代码
2013/08/05 Javascript
JS实现仿中关村论坛评分后弹出提示效果的方法
2015/02/23 Javascript
javascript实现多栏闭合展开式广告位菜单效果实例
2015/08/05 Javascript
手机端转盘抽奖代码分享
2015/09/10 Javascript
基于jQuery和CSS3制作响应式水平时间轴附源码下载
2015/12/20 Javascript
jQuery easyui刷新当前tabs的方法
2016/09/23 Javascript
基于react组件之间的参数传递(详解)
2017/09/05 Javascript
vue-cli配置环境变量的方法
2018/07/09 Javascript
从源码里了解vue中的nextTick的使用
2018/11/22 Javascript
详解vue.js移动端配置flexible.js及注意事项
2019/04/10 Javascript
使用element-ui的el-menu导航选中后刷新页面保持当前选中状态
2019/07/19 Javascript
js 动态校验开始结束时间的实现代码
2020/05/25 Javascript
微信小程序组件生命周期的踩坑记录
2021/03/03 Javascript
Pandas Shift函数的基础入门学习笔记
2018/11/16 Python
python三方库之requests的快速上手
2019/03/04 Python
python实现图像检索的三种(直方图/OpenCV/哈希法)
2019/08/08 Python
python 实现读取csv数据,分类求和 再写进 csv
2020/05/18 Python
Python3使用 GitLab API 进行批量合并分支
2020/10/15 Python
python3实现简单飞机大战
2020/11/29 Python
html5简单示例_动力节点Java学院整理
2017/07/07 HTML / CSS
2014年公司植树节活动方案
2014/03/04 职场文书
学校献爱心活动总结
2014/07/08 职场文书
Nginx服务器添加Systemd自定义服务过程解析
2021/03/31 Servers
解决pytorch 损失函数中输入输出不匹配的问题
2021/06/05 Python
Java对文件的读写操作方法
2022/04/29 Java/Android