接到产品需求,问能不能将前端上传的图片压缩?像移动端上传图片,一般都是超清、高清图片,大小也有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); } }); }) }
|