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 相关文章推荐
对textarea框的代码调试,而且功能上使用非常方便,酷
Jun 30 Javascript
javascript最常用与实用的创建类的代码
Aug 12 Javascript
JS 在指定数组中随机取出N个不重复的数据
Jun 10 Javascript
node.js中的buffer.Buffer.byteLength方法使用说明
Dec 10 Javascript
Bootstrap基本组件学习笔记之按钮组(8)
Dec 07 Javascript
微信小程序 配置文件详细介绍
Dec 14 Javascript
bootstrapValidator 重新启用提交按钮的方法
Feb 20 Javascript
JavaScrpt判断一个数是否是质数的实例代码
Jun 11 Javascript
jQuery.Form实现Ajax上传文件同时设置headers的方法
Jun 26 jQuery
Vue页面骨架屏注入方法
May 13 Javascript
vue 中的 render 函数作用详解
Feb 28 Javascript
Node实现搜索框进行模糊查询
Jun 28 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
解析在apache里面给php写虚拟目录的详细方法
2013/06/24 PHP
php提交post数组参数实例分析
2015/12/17 PHP
js不是基础的基础
2006/12/24 Javascript
在页面上点击任一链接时触发一个事件的代码
2007/04/07 Javascript
jquery退出each循环的写法
2014/02/26 Javascript
jQuery性能优化的38个建议
2014/03/04 Javascript
js调试工具console.log()方法查看js代码的执行情况
2014/08/08 Javascript
JavaScript实现三阶幻方算法谜题解答
2014/12/29 Javascript
jQuery实现的输入框选择时间插件用法实例
2015/02/28 Javascript
Javascript实现图片加载从模糊到清晰显示的方法
2016/06/21 Javascript
JQuery DIV 动态隐藏和显示的方法
2016/06/23 Javascript
关于jquery中动态增加select,事件无效的快速解决方法
2016/08/29 Javascript
详解Node项目部署到云服务器上
2017/07/12 Javascript
Vue利用路由钩子token过期后跳转到登录页的实例
2017/10/26 Javascript
Bootstrap3.3.7导航栏下拉菜单鼠标滑过展开效果
2017/10/31 Javascript
vue中设置height:100%无效的问题及解决方法
2018/07/27 Javascript
浅谈ng-zorro使用心得
2018/12/03 Javascript
Vue和React组件之间的传值方式详解
2019/01/31 Javascript
JavaScript函数重载操作实例浅析
2020/05/02 Javascript
使用Typescript和ES模块发布Node模块的方法
2020/05/25 Javascript
[01:08]DOTA2次级职业联赛 - Wings 战队宣传片
2014/12/01 DOTA
python缩进区别分析
2014/02/15 Python
简单介绍Python2.x版本中的cmp()方法的使用
2015/05/20 Python
Python3.5局部变量与全局变量作用域实例分析
2019/04/30 Python
python中比较两个列表的实例方法
2019/07/04 Python
pycharm实现猜数游戏
2020/12/07 Python
处理HTML5新标签的浏览器兼容版问题
2017/03/13 HTML / CSS
html5利用canvas实现颜色容差抠图功能
2019/12/23 HTML / CSS
3D空间设计学生找工作的自我评价
2013/10/28 职场文书
内容编辑个人求职信
2013/12/10 职场文书
2014年最新学习全国两会精神心得
2014/03/17 职场文书
股份合作协议书
2014/04/12 职场文书
2014年便民服务中心工作总结
2014/12/20 职场文书
专业技术职务聘任证明
2015/03/02 职场文书
高中历史教学反思
2016/02/19 职场文书
2019通用版新员工入职培训方案!
2019/07/11 职场文书