方式一: 自動上傳
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> 15</el-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); },