因为最近项目做一个webApp的页面,需要上传图片,总结了一下,思路如下:
一、监听一个 input (type=‘file‘) 的 change 事件,然后拿到文件的 file;
<input id="img-input" class="upload-input" type="file" accept="image/*" id="imgbox" multiple/>
二、把 file 转成 dataURL;
/** * file 转成 dataURL * @param file 文件 * @param callback 回调函数 */function fileToDataURL (file, callback) { ?const reader = new window.FileReader(); ?reader.onload = function (e) { ???callback(e.target.result); ?}; ?reader.readAsDataURL(file);}
三、然后用 canvas 绘制图片,绘制的时候经过算法按比例裁剪,然后再把 canvas 转成 dataURL;
/** * 使用 canvas 压缩 dataURL * @param dataURL * @param ratio * @param callback */function compressDataURL (dataURL, ratio, callback) { ?const img = new window.Image(); ?img.src = dataURL; ?// onload ?img.onload = function () { ???const canvas = document.createElement(‘canvas‘); ???const ctx = canvas.getContext(‘2d‘); ???canvas.width = 100 * ratio.w; ???canvas.height = 100 * ratio.h; ???const RATIO = canvas.width / canvas.height; ???let cutx = 0; ???let cuty = 0; ???let cutw = img.width; ???let cuth = img.height; ???if (cutw / cuth > RATIO) { ?????// 宽超过比例了]] ?????let realw = cuth * RATIO; ?????cutx = (cutw - realw) / 2; ?????cutw = realw; ???} else if (cutw / cuth < RATIO) { ?????// 长超过比例了]] ?????let realh = cutw / RATIO; ?????cuty = (cuth - realh) / 2; ?????cuth = realh; ???} ???ctx.drawImage(img, cutx, cuty, cutw, cuth, 0, 0, canvas.width, canvas.height); ???const ndata = canvas.toDataURL(‘image/jpeg‘, 1); ???callback(ndata); ?};}
四、 dataURL 转成 blob;
/** * dataURL 转成 blob * @param dataURL * @return blob */function dataURLtoBlob (dataURL) { ?let binaryString = atob(dataURL.split(‘,‘)[1]); ?let arrayBuffer = new ArrayBuffer(binaryString.length); ?let intArray = new Uint8Array(arrayBuffer); ?let mime = dataURL.split(‘,‘)[0].match(/:(.*?);/)[1] ?for (let i = 0, j = binaryString.length; i < j; i++) { ???intArray[i] = binaryString.charCodeAt(i); ?} ?let data = [intArray]; ?let result; ?try { ???result = new Blob(data, { type: mime }); ?} catch (error) { ???window.BlobBuilder = window.BlobBuilder || ?????window.WebKitBlobBuilder || ?????window.MozBlobBuilder || ?????window.MSBlobBuilder; ???if (error.name === ‘TypeError‘ && window.BlobBuilder){ ?????var builder = new BlobBuilder(); ?????builder.append(arrayBuffer); ?????result = builder.getBlob(type); ???} else { ?????throw new Error(‘暂不支持‘); ???} ?} ?return result;}
五、把 blob append 到 FormData 的实例对象,然后上传。
var imgBox =document.getElementById("imgbox");
var blobArr = []; ?//参数可以传给后台imgBox.change = function(e){ ??var file=this.files; ???for(var i=0;i<event.target.files.length;i++){ ?????????fileToDataURL(file[i], function(dataURL){ ??????????????compressDataURL(dataURL,function (newDataURL) ?{ const newBlob = this.dataURLtoBlob(newDataURL,file[i]); ????????????????????//const fileOfBlob = new File([newBlob], file[i].name); ??//可将blob转换成file格式 ????????????????????blobArr.push(newBlob); ??????????????}); ????????}); ???} ???????}
//上传
var formData = new FormData();
for (var i = 0, len = blobArr.file.length; i < len; i++) {
formData.append("file" + i, options.file[i]);
}
let xhr = new XMLHttpRequest();
// 进度监听
// xhr.upload.addEventListener(‘progress‘, progFoo, false);
// 加载监听
// xhr.addEventListener(‘load‘, loadFoo, false);
// 错误监听
// xhr.addEventListener(‘error‘, errorFoo, false);
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
// 上传成功,获取到结果 results
let results = JSON.parse(xhr.responseText);
// ......
}
} else {
// 上传失败
}
}
};
xhr.open(‘POST‘, ‘/api/upload‘, true);
xhr.send(formData);
});
H5压缩图片上传(FileReader +canvas)
原文地址:http://www.cnblogs.com/dakini/p/7454592.html