接到产品需求,问能不能将前端上传的图片压缩?像移动端上传图片,一般都是超清、高清图片,大小也有10M,甚至一张图片大小有15M左右,这样大的图片上传到腾讯云或者阿里云(没使用服务器上传图片)一方面上传速度慢,影响体验,另一方面体积太大占空间,图片压缩避免了,网上搜到了很多这方面介绍的网址,大多数都是用canvas来实现(不说了,马上开干)!。
实现过程 (10M => 200k左右)
1. 图片裁剪
大体的思路是将图片抽样显示在canvas上,然后用通过canvas.toDataURL
方法得到base64字符串来实现压缩。上代码!!!
const file: {} = e.target.files[0];
const reader = new FileReader(),
img = new Image();
const canvas = document.createElement('canvas');
const context = canvas.getContext('2d');
reader.readAsDataURL(file);
img.onload = function () {
const originWidth = this['width'];
const originHeight = this['height'];
const maxWidth = 750, maxHeight = 400;
let targetWidth = originWidth, targetHeight = originHeight;
if (originWidth > maxWidth || originHeight > maxHeight) {
if (originWidth / originHeight > maxWidth / maxHeight) {
targetWidth = maxWidth;
targetHeight = Math.round(maxWidth * (originHeight / originWidth));
} else {
targetHeight = maxHeight;
targetWidth = Math.round(maxHeight * (originWidth / originHeight));
}
}
canvas.width = targetWidth;
canvas.height = targetHeight;
context.clearRect(0, 0, targetWidth, targetHeight);
context.drawImage(img, 0, 0, targetWidth, targetHeight);
const dataUrl = canvas.toDataURL('image/jpeg');
updateImgForBase64(dataUrl);
}
reader.onload = function (e) {
img.src = e.target['result'];
};
|
2. 上传到腾讯云
项目中图片是保存在腾讯云中,这里就需要用到腾讯JavaScript SDK,按照SDK文档去新建存储桶获取Bucket、Region,直接上代码:
updateImgForBase64(img: string, type: string = 'jpeg'): Promise<any> {
const vm = this;
const storeAs = `avatar/${new Date().getTime()}-${this.guid()}.${type}`;
const dataURLtoFile: Function = (dataurl, filename) => {
const arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1];
const bstr = atob(arr[1]);
let n = bstr.length;
const u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new File([u8arr], filename, {type: mime});
};
const file = dataURLtoFile(img, type);
return new Promise((resolve, reject) => {
this.cos.sliceUploadFile({
Bucket: 'your bucket',
Region: 'your region',
Key: storeAs,
Body: file
}, function (err, data) {
if (err) {
reject(JSON.stringify(err));
} else {
resolve(url);
}
});
})
}
|