最近做的项目中用到了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上传图片(可多张上传)的更多相关文章

  1. 解决thinkphp批量上传图片只有一张上传成功解决方案

    批量上传时 存在一个生成文件名的问题 如果出现此bug,则不要用原生的生成规则来命名图片文件名 如果你试试同时上传两个不同类型,例如一张jpg,一张png,你就发现的确是可以两张同时上传的! 方案1: ...

  2. ueditor1.3.6jsp版在struts2应用中上传图片报"未找到上传文件"解决方案

    摘要: ueditor1.3.6jsp版在struts2应用中上传图片报"未找到上传文件"解决方案 在struts2应用中使用ueditor富文本编辑器上传图片或者附件时,即使配置 ...

  3. 基于h5的图片无刷新上传(uploadifive)

    基于h5的图片无刷新上传(uploadifive) uploadifive简介 了解uploadify之前,首先了解来一下什么是uploadify,uploadfy官网,uploadify和uploa ...

  4. 微信多媒体上传图片,创建卡券上传 LOGO

    //*****************************************多媒体上传图片 begin******************************************** ...

  5. Windows环境下用C#编程将文件上传至阿里云OSS笔记

    Windows环境下用C#编程将文件上传至阿里云OSS笔记 本系列文章由ex_net(张建波)编写,转载请注明出处. http://blog.csdn.net/ex_net/article/detai ...

  6. Windows下GIT安装与使用(上传远程端)

    Windows下GIT安装与使用(上传远程服务器) 1.  登陆http://msysgit.github.io/并下载Git 2.  打开下载的exe文件,一路默认(路径可以去修改).有可能电脑需要 ...

  7. Linux下自动备份MySQL数据库并上传到远程FTP服务器

    Linux下自动备份MySQL数据库并上传到远程FTP服务器且删除指定日期前的备份Shell脚本 说明:  1.备份MySQL数据库存放目录/var/lib/mysql下面的xshelldata数据库 ...

  8. 使用Windows下的git工具往github上传代码 踩坑记录

    使用Windows下的git工具往github上传代码 踩坑记录 背景 由于以前接触的项目都是通过svn进行版本控制,现在公司项目使用git,加上自己平时有一个练手小项目,趁着周末试着把项目上传到自己 ...

  9. iOS移动下上传图片失败解决 (上传多图,带其他参数)

    项目中有一个主要的功能,就是上传图片,结结果移动真的是很奇怪,WiFi,联通,电信都没有问题的情况下,居然在移动下不行,真的是很头疼.不过好在最后是解决了 项目的网络请求我是采用ASIHttpRequ ...

随机推荐

  1. poj1988

    知道了并查集写的问题后,我也明白了为什么之前这道题TLE的原因: 有这道题的合并操作不难想到用并查集维护: 由于并查集易于向上查询而不易于向下查询 所以对于询问方块x下面有多少个方块,我们可以转化为立 ...

  2. SQL中取当前记录的ID----->SCOPE_IDENTITY()

    SQL Server 2000中,有三个比较类似的功能:他们分别是:SCOPE_IDENTITY.IDENT_CURRENT 和 @@IDENTITY,它们都返回插入到 IDENTITY 列中的值.I ...

  3. MVC View基础

    View主要用于呈现数据.由于Controller和相关的Service已经处理完业务逻辑并将结果打包成model实体,View只需要怎么去获得model并将其转为Html 1选择需要渲染的视图 在上 ...

  4. 热修复 RocooFix篇(一)

    吐槽之前先放一张大帅图. (md 这张图貌似有点小 不纠结这个了==) 有时候项目刚刚上线或者迭代 测试或者在线上使用测出一个bug来 真让人蛋疼 不得不重新改bug测试 打包混淆上线感觉就向find ...

  5. [liu yanling]软件测试的分类

    按测试的对象或范围分类: 单元测试.文档测试.系统测试等. 按测试目的分类: 功能测试.回归测试.性能测试.可靠性测试.安全性测试和兼容性测试 等.  根据测试过程中被测软件是否被执行: 分为静态测试 ...

  6. C#索引器的作用及使用

    1. 作用: 可以使得类和实例能够像数组那样使用一样,又称为带参属性 2. 区分 (1)索引器与数组的比较: 索引器的索引值不受类型限制.用来访问数组的索引值一定是整数,而索引器可以是其他类型的索引值 ...

  7. Java笔记(十六)……内部类

    内部类概述 内部类是将一个类定义在另一个类里面,对里面那个类就成为内部类(内部类,嵌套类). 当描述事物时,事物的内部还有事物,该事物用内部类来描述,因为内部事物在使用外部事物的内容 访问特点 内部类 ...

  8. HDOJ-ACM1004(JAVA)

    转载声明:原文转自http://www.cnblogs.com/xiezie/p/5502876.html JAVA语言实现: 拿到题目第一反应是用HashMap实现,但是感觉用HashMap实在太浪 ...

  9. windows 7 中将“我的电脑”锁定到任务栏

    1.在桌面右击->新建->快捷方式 2.输入%SystemRoot%\explorer.exe /E,::{20D04FE0-3AEA-1069-A2D8-08002B30309D}点击下 ...

  10. glusterfs repo

    Installing Gluster For RPM based distributions, if you will be using InfiniBand, add the glusterfs R ...