需求:
项目中需要上传附件,类型包括pdf、word、excel、图片等,要求如果上传的文件中有图片需要自动压缩。
解决方案:
在web端使用canvas把图片压缩成较小的格式。
开发过程中遇到不少难点,贴出代码供大家参考,js代码:
/*
说明:这是上传插件,基于jquery(暂时还没有做成插件的形式)
时间:2019-01-25
作者:gaobin
*/
var ud_upload = {
paras: {
btn: "",//触发 按钮 的id
fileName: "AttachmentFile",//上传file的名称
uploadPath: "",//上传路径
accept: "image/*",// 图片"image/*",所有文件:*/*
isMultiple: true,//默认上传多个文件
data: function () {
return {};
},
complete: function () { }
},
upload: function (file, name) {
console.log("上传");
var _this = this;
//开始上传非图片文件
var formData = new FormData();
//压缩后的图片放到form中
formData.append("AttachmentFile", file);
if (typeof file === "string") {
formData.append("AttachmentFileTitle", name);
}
var _data = _this.paras.data();
//向form中添加客户参数
for (var key in _data) {
formData.append(key, _data[key]);
}
$.ajax({
url: _this.paras.uploadPath,
type: 'POST',
dataType: "JSON",
data: formData,
processData: false, //tell jQuery not to process the data
contentType: false, //tell jQuery not to set contentType
async: false,
cache: false,
success: function (res) {
_this.paras.complete(res);
//filesArr.count--;
//delete filesArr.arr[0];
}
});
// }
},
filesArr: { count: 0, arr: [] },
callback: function callback(img, file) {
//这里传递过来的img图片对象是装载完毕的
//开始压缩img
var data = compress(img, {});
img = null;
this.uploadImg(data, file.name);
},
init: function (paras) {
//显示上传中
//top.loading();
var _this = this;
//初始参数
var _p = $.extend({}, _this.paras, paras);
_this.paras = _p;
$("#" + paras.btn).bind("click", function () {
//触发上传,这里id要唯一 ,否则会出错
$("#" + paras.fileName + _p.btn).click();
});
var _temp_form = $("<form class='hidden'>", {
//"id": "form_update_id",
// "enctype": "multipart/form-data"
});
_temp_form.append($("<input>", {
"id": _p.fileName + _p.btn,
"type": "file",
"accept": _p.accept,
"multiple": _p.isMultiple,
"name": _p.fileName,//上传文件的名称,需要与action参数的名称一致
change: function () {
//起始上传任务
//这里非常关键,如果直接循环this.files将只能上传最后一个文件
var files = Array.prototype.slice.call(this.files);
var imgarray = [];
files.forEach(function (fileItem, fi) {
//图片以image开头,其他以appliction开头
if (fileItem.type.indexOf("image/") == 0) {
//file转image对象
var reader = new FileReader();
reader.onload = function () {
imgarray[fi] = new Image();
//关键点,要传入this,否则获取不到img中的数据
imgarray[fi].onload = function () {
//开始压缩img
var base64 = compress(imgarray[fi], {});
//放到队列中
console.log(fileItem.name + base64);
// _this.filesArr.arr.push(base64);
_this.upload(base64, fileItem.name);
}; //当图像装载完毕
imgarray[fi].src = event.target.result;//base64
};
reader.readAsDataURL(fileItem);//读取图像文件 result 为 DataURL, DataURL 可直接 赋值给 img.src
} else {
//非图片将验证文件大小,大于4MB禁止上传
if (files[fi].size > (4 * 1024 * 1024)) {
$.msg.alert("《" + files[fi].name + "》大于4兆,禁止上传");
//因多文件上传,因此不停止循环
// break;
}
//上传
//_this.filesArr.arr.push(fileItem);
_this.upload(files[fi]);
}
});
//-end 文件循环
}
}));
$("body").append(_temp_form);
return this;
}
};
服务端代码没什么难点,如果不会写可以下载。
难点:
同时上传多个文件时发现只能最后一个上传成功,开始我是直接使用this.files循环上传,测试了一下午发现这一行代码比较关键, var files = Array.prototype.slice.call(this.files); 改成这样后多个文件可以正常上传了。
全部源代码可下载:同时上传多个文件,图片自动压缩