非常感谢文章作者技术分享,请多多鼓励他们
文章链接:https://blog.csdn.net/weixin_44134899/article/details/95046994
场景:在Vue项目里,利用ElementUI的upload组件,上传图片,在图片上传前,对图片进行压缩。
做法概述:在before-upload方法中对图片文件进行处理,并返回处理后的文件。
beforeUpload方法中,除了可以返回图片校验时的true/false,还可以以return new Promise的方式返回文件,如返回文件,则上传时,以返回的文件为准上传。
详细代码:
1.源码中有个判定:
const before = this.beforeUpload(rawFile)
if(before && before.then) {
before.then( processedFIle => {
const fileType = Object.prototype.toString.call(processedFIle) // 获取文件的格式
if(fileType === '[object File]' || fileType === '[object Blob]') {
...
}
})
}
即:如果收到beforeUpload方法中传输过来的参数是File或者Blob格式,则将此文件作为文件参数请求request,否则用原文件rawFile为参数。因此,我们将文件压缩后,转换成File或者Blob格式resolve即可。
2.在beforeUpload方法中添加
beforeAvatarUpload(file) {
var that = this;
return new Promise((resolve, reject) => {
const isJPG = file.type === "image/jpeg";
const isPNG = file.type === "image/png";
const isLt1M = file.size / 1024 / 1024 < 1;
let bool = false;
let msg = "";
if (isJPG || isPNG) {//判断是否符合格式要求
bool = true;
} else {
that.$message.error("上传文件必须是jpg、png格式!");
return false;
}
if (bool && !isLt1M) {//如果格式符合要求,但是size过大,对图片进行处理
let image = new Image(),
resultBlob = "";
image.src = URL.createObjectURL(file);
image.onload = () => {
resultBlob = that.compressUpload(image);//Blob
resolve(resultBlob);
};
} else if (bool && isLt1M) {
resolve(file);//file
}
});
},
compressUpload(image) {
let canvas = document.createElement("canvas");//创建画布元素
let ctx = canvas.getContext("2d");
let initSize = image.src.length;
let { width } = image,
{ height } = image;
canvas.width = width;
canvas.height = height;
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(image, 0, 0, width, height);
let compressData = canvas.toDataURL("image/jpeg", 0.8); //等比压缩
let blobImg = this.dataURItoBlob(compressData);//base64转Blob
return blobImg;
},
dataURItoBlob(data) {
let byteString;
if (data.split(",")[0].indexOf("base64") >= 0) {
byteString = atob(data.split(",")[1]);//转二进制
} else {
byteString = unescape(data.split(",")[1]);
}
let mimeString = data
.split(",")[0]
.split(":")[1]
.split(";")[0];
let ia = new Uint8Array(byteString.length);
for (let i = 0; i < byteString.length; i += 1) {
ia[i] = byteString.charCodeAt(i);
}
return new Blob([ia], { type: mimeString });
},
3.说明:
添加以上代码后,文件传输服务器的时候,传输的是压缩的文件,但在on-success钩子中,参数file、fileList中依然是原图片的信息,即未压缩的图片信息,所以,当在on-success中打印file时,如果打印的文件尺寸没有改变,并不是没有压缩传输成功。如果想要确定是否传输了压缩文件至服务器,可以在接口请求时让后台人员查看一下传输时的文件参数。