使用elementui组件el-upload 基于canvas进行图片压缩
参考网页:https://segmentfault.com/a/1190000012608763
主要解释了将file文件转为dataUrl,进行压缩再生成 blob对象 再生成formData对象 上传到服务器
主要代码:
1、修改el-upload的action=“dxx”(随便写) 2、需要放到userinfo/index里的methods里 compress(img) { let canvas = document.createElement("canvas"); let ctx = canvas.getContext("2d"); let initSize = img.src.length; let width = img.width; let height = img.height; canvas.width = width; canvas.height = height; ctx.fillStyle = "#fff"; ctx.fillRect(0, 0, canvas.width, canvas.height); ctx.drawImage(img, 0, 0, width, height); //进行最小压缩 let ndata = canvas.toDataURL("image/jpeg", 0.1); return ndata; }, dataURLtoBlob(base64Data) { var byteString; if (base64Data.split(",")[0].indexOf("base64") >= 0) byteString = atob(base64Data.split(",")[1]); else byteString = unescape(base64Data.split(",")[1]); var mimeString = base64Data .split(",")[0] .split(":")[1] .split(";")[0]; var ia = new Uint8Array(byteString.length); for (var i = 0; i < byteString.length; i++) { ia[i] = byteString.charCodeAt(i); } return new Blob([ia], { type: mimeString }); }, dataURLtoFile(dataurl, filename) { var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1], bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n); while (n--) { u8arr[n] = bstr.charCodeAt(n); } return new File([u8arr], filename, {type: mime}); }, post(rawFile) { const { uid } = rawFile; const options = { headers: this.my, withCredentials: this.withCredentials, file: rawFile, data: '', filename: this.name, action: this.action, onProgress: e => { this.onProgress(e, rawFile); }, onSuccess: res => { this.onSuccess(res, rawFile); delete this.reqs[uid]; }, onError: err => { this.onError(err, rawFile); delete this.reqs[uid]; } }; const req = this.httpRequest(options); this.reqs[uid] = req; if (req && req.then) { req.then(options.onSuccess, options.onError); } }, beforeAvatarUpload(file) { const isJPG = file.type === 'image/jpeg'; const isLt2M = file.size / 1024 / 1024 < 2; if (!isJPG) { this.$message.error('上传头像图片只能是 JPG 格式!'); return 0; } if (!isLt2M) { this.$message.error('上传头像图片大小不能超过 2MB!'); return 0; } let self=this; if (!file || !window.FileReader) return; let reader = new FileReader(); reader.readAsDataURL(file); reader.onloadend = function() { let result = this.result; let img = new Image(); img.src = result; img.onload = function() { let data = self.compress(img); self.imgUrl = result; let blob = self.dataURLtoBlob(data); self.tempfile=self.dataURLtoFile(data,file.name); var formData = new FormData(); formData.append("pic", blob); let config = { headers:{'Content-Type':'multipart/form-data'} } self.$http.post('' + LOCALHOST_URL + '/api/uploadPic',formData,config).then((response) => { if(response.data.success=true) { self.$message({ type: 'success', message: '修改成功!' }); self.imageUrl = URL.createObjectURL(formData.get('pic')); } }, (response) => { console.log(response) } ) } } }, 3、api router.post('/api/uploadPic',upload.single('pic'),function (req, res) { let file = req.file; let tmp_path = file.path; let target_path = './upload/pic/' + file.filename + '.jpg'; let resBody={}; console.log(file); fs.rename(tmp_path, target_path, function (err) { if (err) throw err; fs.unlink(tmp_path, function () { }) }); let id = req.api_user.id; let url='https://dc17.xin/api/uploadpic/'+file.filename+'.jpg'; //TODO 上传至服务器后修改 connection.query('UPDATE user set thumb=? WHERE id =? ',[url,id], function (err) { if (err) { resBody.error = 500; return res.send(resBody); } else { resBody.success = true; return res.send(resBody); } }) });
注意事项:
参考(https://www.jianshu.com/p/7a41b080a9d2)提到了上传的formdata的headers必须要是{ "Content-Type": "multipart/form-data" }
不然不能被multer插件拦截