vue + element 上传图片时压缩图片
方式一: 自动上传
html结构部分
1 <el-upload 2 class="avatar-uploader" 3 action="/vab-mock-server/cloud/manager/common/aliyunStorage/upload" 4 :on-success="handleMainSuccess" 5 :before-upload="beforeAvatarUpload" 6 :on-error="handleError" 7 :show-file-list="false"> 9 <img 10 v-if="ruleForm.businessLicense" 11 :src="ruleForm.businessLicense" 12 class="avatar"/> 14 <i v-else class="el-icon-plus avatar-uploader-icon">i> 15el-upload>
主要使用before-upload 钩子函数,涉及插件 image-Conversion
//插件安装
npm i image-conversion --save
//插件引入
import * as imageConversion from 'image-conversion';
javaScript部分
beforeAvatarUpload(file) {
const isJpgOrPng = file.type === "image/jpeg" || file.type === "image/png";
// 这里判断图片格式是否为jpeg或png 看实际情况使用
if (!isJpgOrPng) {
this.$message.error("上传图片只能是 JPG 或 PNG 格式!");
return false;
}
const isLtM = file.size / 1024 / 1024 >= 1 // 这里对于大于 1M 的图片都进行压缩处理
// 使用 Promise()防止没处理文件就上传
return new Promise((resolve) => {
// 小于1M 不压缩
if (!isLtM) {
resolve(file)
}
// 压缩到400KB,这里的400就是要压缩的大小,可自定义
imageConversion.compressAccurately(file, 400).then((res) => {
resolve(res)
})
//compressAccurately有多个参数时传入对象
//imageConversion.compressAccurately(file, {
// size: 1024, //图片大小压缩到1024kb
// width:1280 //宽度压缩到1280
//}).then(res => {
//resolve(res)
//})
})
},
方式二 手动上传
接口要以file类型随表单一起提交,这时就不能自动上传了,那么 el-upload组件的auto-upload这个属性就为false.
auto-upload为false 会导致 before-upload失效。但可以用 on-change钩子函数代替
但是这个钩子函数 不能接受Promise回调,所以使用imageConversion异步返回一个resolve结果,没办法接收,所以这里用到另一个压缩图片的方法,使用canvas画布压缩,
下面的压缩函数,可以放到你的公用工具js里
/** 图片压缩,默认同比例压缩 * @param {Object} fileObj * 图片对象 * 回调函数有一个参数,base64的字符串数据 */ export function compress(fileObj, callback) { try { const image = new Image() image.src = URL.createObjectURL(fileObj) image.onload = function() { const that = this // 默认按比例压缩 let w = that.width let h = that.height const scale = w / h w = fileObj.width || w h = fileObj.height || (w / scale) let quality = 0.7 // 默认图片质量为0.7 // 生成canvas const canvas = document.createElement('canvas') const ctx = canvas.getContext('2d') // 创建属性节点 const anw = document.createAttribute('width') anw.nodeValue = w const anh = document.createAttribute('height') anh.nodeValue = h canvas.setAttributeNode(anw) canvas.setAttributeNode(anh) ctx.drawImage(that, 0, 0, w, h) // 图像质量 if (fileObj.quality && fileObj.quality <= 1 && fileObj.quality > 0) { quality = fileObj.quality } // quality值越小,所绘制出的图像越模糊 const data = canvas.toDataURL('image/jpeg', quality) // 压缩完成执行回调 const newFile = convertBase64UrlToBlob(data) callback(newFile) } } catch (e) { console.log('压缩失败!') } } function convertBase64UrlToBlob(urlData) { const bytes = window.atob(urlData.split(',')[1]) // 去掉url的头,并转换为byte // 处理异常,将ascii码小于0的转换为大于0 const ab = new ArrayBuffer(bytes.length) const ia = new Uint8Array(ab) for (let i = 0; i < bytes.length; i++) { ia[i] = bytes.charCodeAt(i) } return new Blob([ab], { type: 'image/png' }) }
HTML部分
<el-upload class="upload-demo" ref="uploadPrice" action="#" :auto-upload="false" :on-change="fileChange" :on-success="priceSuc" :show-file-list="false" :limit="5" multiple > <el-button slot="trigger" size="mini" type="primary" >添加附件el-button > el-upload>
JavaScript部分
fileChange(file, fileList) { this.$refs.uploadPrice.clearFiles(); let _this = this; let obj = { imgUrl: "", name: "", }; let fileListData = []; for (let x = 0; x < fileList.length; x++) { let item1 = fileList[x]; this.GLOBAL.compress(item1.raw, function (val) { let newfile = new window.File([val], file.name, { type: file.type }); newfile.uid = file.uid; fileListData.push(newfile); }); var file = item1.raw; obj.name = item1.name; var reader = new FileReader(); reader.onload = function (e) { //转base64 obj.imgUrl = e.target.result; _this.fileArr.push(obj); }; reader.readAsDataURL(file); } this.$set(this.form, "fileList", fileListData); // console.log(this.form.fileList); },