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 相关文章推荐
B/S模式项目中常用的javascript汇总
Dec 17 Javascript
在JavaScript中操作数组之map()方法的使用
Jun 09 Javascript
vue实现简单实时汇率计算功能
Jan 15 Javascript
js模态对话框使用方法详解
Feb 16 Javascript
基于JavaScript实现多级菜单效果
Jul 25 Javascript
微信小程序图片选择区域裁剪实现方法
Dec 02 Javascript
利用JQUERY实现多个AJAX请求等待的实例
Dec 14 jQuery
p5.js实现动态图形临摹
Oct 23 Javascript
electron 如何将任意资源打包的方法步骤
Apr 16 Javascript
vue-amap根据地址回显地图并mark的操作
Nov 03 Javascript
在实例中重学JavaScript事件循环
Dec 03 Javascript
javascript拖曳互换div的位置实现示例
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
PHP中实现图片的锐化
2006/10/09 PHP
Windows下XDebug 手工配置与使用说明
2010/07/11 PHP
ThinkPHP分页实例
2014/10/15 PHP
PHP进行批量任务处理不超时的解决方法
2016/07/11 PHP
PHP数据源架构模式之表入口模式实例分析
2020/01/23 PHP
细品javascript 寻址,闭包,对象模型和相关问题
2009/04/27 Javascript
jquery仿QQ商城带左右按钮控制焦点图片切换滚动效果
2013/06/27 Javascript
AngularJS初始化过程分析(引导程序)
2014/12/06 Javascript
jquery队列函数用法实例
2014/12/16 Javascript
jQuery中animate()方法用法实例
2014/12/24 Javascript
js实现无缝循环滚动
2020/06/23 Javascript
微信小程序 触控事件详细介绍
2016/10/17 Javascript
jquery Ajax实现Select动态添加数据
2017/06/08 jQuery
Linux系统中利用node.js提取Word(doc/docx)及PDF文本的内容
2017/06/17 Javascript
浅谈vue的iview列表table render函数设置DOM属性值的方法
2017/09/30 Javascript
JS实现的简单表单验证功能示例
2017/10/13 Javascript
jquery实现搜索框功能实例详解
2018/07/23 jQuery
vue微信分享出来的链接点开是首页问题的解决方法
2018/11/28 Javascript
JS执行控制之节流模式实例分析
2018/12/21 Javascript
多个vue子路由文件自动化合并的方法
2019/09/03 Javascript
[04:30]显微镜下的DOTA2第五期——拉比克
2013/09/26 DOTA
Python爬虫框架Scrapy基本用法入门教程
2018/07/26 Python
在pycharm中使用git版本管理以及同步github的方法
2019/01/16 Python
Python中函数的基本定义与调用及内置函数详解
2019/05/13 Python
详解pandas DataFrame的查询方法(loc,iloc,at,iat,ix的用法和区别)
2019/08/02 Python
Python中断多重循环的几种方式详解
2020/02/10 Python
英国工具中心:UK Tool Centre
2017/07/10 全球购物
eBay奥地利站:eBay.at
2019/07/24 全球购物
土木工程个人自荐信范文
2013/11/30 职场文书
大学生求职信范文
2014/05/24 职场文书
民政工作个人总结
2015/02/28 职场文书
运动会通讯稿600字
2015/07/20 职场文书
股东协议书范本2016
2016/03/21 职场文书
Nginx实现高可用集群构建(Keepalived+Haproxy+Nginx)
2021/05/27 Servers
关于Oracle12C默认用户名system密码不正确的解决方案
2021/10/16 Oracle
mysql查找连续出现n次以上的数字
2022/05/11 MySQL