因为最近项目做一个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);
});