前端实现图片压缩上传
目录
前言
上传图片/视频/文件是我们经常会遇到的问题,但是一旦图片过大就会导致不好的操作体验。
图片上传是前端中常见的的业务场景。无论是前台还是后台,适当的对图片进行压缩处理,可以显著的提升用户体验。
而在后台管理系统中,图片压缩不仅仅能够提升后台管理员操作体验,更是可以防止后台设置过大的图片导致前台图片加载过久,从而影响用户体验。
实践
先看下面两张图片,它们表面看上去是一模一样的,但实际上各自所占用的内存大小相差了 180 倍。
可以看到右边的图片是 22.3MB,而左侧的图片只有 127KB,但是实际上这两张图片的大小都是 22.3MB。
最近在开发中遇到这样的一个需求,需要把用户上传的图片先进行一次压缩,然后再保存到服务器,这里我们除了优先考虑压缩图片的大小外,还要顾及图片压缩后的清晰度问题。
经过对比,图片并没有明显的失真情况,下面给大家分享一下,我的解决方法。
具体的思路是:
通过 FormData 构造函数创建一个空对象,将图片绘制到 canvas 画布上,然后再进行压缩。用户上传的文件超过一定的大小后就可以执行压缩的操作,当然如果图片太小的话,我们就没必要再压了。建议采用宽高等比例的方式来压缩,不然可能会出现图片变形的情况。
这里我采用 element 的文件上传控件来上传图片:
<el-upload class="avatar-uploader" :action="GLOBAL.serverFileUrl" name="file" drag :show-file-list="false" :on-change="beforeAvatarUpload" > <i class="el-icon-plus avatar-uploader-icon"></i> </el-upload>
定义了三个事件方法:
//图片上传之前处理事件 beforeAvatarUpload(file) { console.log(file); const isJpgPng = file.raw.type === "image/jpeg" || file.raw.type === "image/png"; if (!isJpgPng ) { this.GLOBAL.messageEvent("error","上传头像图片只能是 JPG/PNG 格式!"); } else { this.compressImg(file.raw); } return isJpgPng; },
compressImg(file) { let that = this; // ?通过 FormData 构造函数创建一个空对象 let formData = new FormData(); let reader = new FileReader(); // ?将读取到的文件编码成 DataURL reader.readAsDataURL(file); // ?压缩图片 reader.onload = function(ev) { try { // ?读取图片来获得上传图片的宽高 let img = new Image(); img.src = ev.target.result; img.onload = function(ev) { // ?将图片绘制到 canvas 画布上进行压缩 let canvas = document.createElement("canvas"); let context = canvas.getContext("2d"); let imgwidth = img.width; let imgHeight = img.height; // ?按比例缩放后图片宽高; let targetwidth = imgwidth; let targetHeight = imgHeight; // ?/如果原图宽大于最大宽度 if (targetWidth > targetHeight) { // ?原图宽高比例 let scale = targetHeight / 1280; targetHeight = 1280; targetWidth' = targetwidth / scale; } else { // ?原图宽高比例 let scale = targetWidth / 1280; targetWidth = 1280; targetHeight = targetHeight / scale; } // ?缩放后高度仍然大于最大高度继续按比例缩小 canvas.width = targetwidth; //canvas 的宽=图片的宽 canvas.height = targetHeight; //canvas 的高=图片的高 context.clearRect(0,0, canvas.width, canvas.height); context.drawImage(this, 0, 0, canvas.width, canvas.height); let data = "": // ?如果图片小于 0.6Mb,不进行压缩,并返回二进制流 if (file.size <= 628288) { data = canvas.toDataURL("image/jpeg"); formData.append("file", file); that.handleChange(file); } // ?如果图片大于 e.6Mb,进行压缩,并返回二进制流 else { // todo 压缩文件大小比例 data = canvas.toDataURL("image/jpeg",0.4); let paper = that.GLOBAL.dataURLtoFile(data, file.name); formData.append("file", paper); that.handleChange(paper); } }; } catch (error) { console.log("出现错误",error); } }; },
// todo 调用上传接口 文件提交给后台 handleChange(file) ( let formData = new FormData( ); formData.append("file",file.raw || file); console.log(formData); brandServices.uploadFile(formData).then(res => { if (res.data.errno === 0) { this.imgUrl = res.data.data; this.dialogImageUrl = URL.createObjectURL(file); this.GLOBAL.messageEvent("success",res.data.message); } else { this.GLOBAL .messageEvent("error",res .data.message); } }); }
总结
先进行图片上传前的验证;接着再对图片实现压缩的操作;最后就可以把文件流提交给后台。
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。
码云笔记 » 前端实现图片压缩上传
码云笔记 » 前端实现图片压缩上传