現有如下需求
1、用戶可以選擇多張圖片,點擊按鈕完成上傳
2、向后台發送的數據必須為base64位編碼的格式
3、圖片名以下標命名
4、接口只支持單張圖片的上傳,上傳成功后返回一個線上的圖片地址
5、最終拿到一個長度為選擇的圖片的數量,內容是每張圖片返回的線上圖片地址的一個數組
實現思路
1、選中圖片后即時的將選擇的圖片轉換為base64存入一個數組中,刪除該圖片時也在數組中將該圖片刪除,始終保證存放base64的數組和已選擇的圖片相對應
2、點擊上傳按鈕利用 for of 遍歷 base64 數組,在每一遍的循環中請求上傳圖片的接口,傳遞當前圖片的base64編碼和當前循環的下標
3、等待接口返回結果,將返回的結果存入一個數組中,在進行下一次循環
4、循環完畢后拿到存放結果的數組
從思路上看我們需要重點關注的就是如何處理調用接口返回結果后再進行下一次循環,並如何在循環外邊拿到返回的數組
開始擼碼
<template> <div class="about"> <!-- action:必填,圖片上傳地址,我們為異步上傳因此此處用井號代替 on-preview:點擊文件列表中已上傳的文件時的鈎子 on-remove:文件列表移除文件時的鈎子 auto-upload:是否在選取文件后立即進行上傳 multiple:是否支持多選文件 limit:最大允許上傳個數 on-change:文件狀態改變時的鈎子,添加文件、上傳成功和上傳失敗時都會被調用 on-exceed:文件超出個數限制時的鈎子 accept:接受上傳的文件類型(thumbnail-mode 模式下此參數無效) --> <el-upload action="#" list-type="picture-card" :on-preview="handlePictureCardPreview" :on-remove="handleRemove" :auto-upload="false" :multiple="true" :limit="5" :on-change="changeIamge" :on-exceed="onExceed" accept="image/*" > <i class="el-icon-plus"></i> {{base64ImageData.length}}/5 </el-upload> <el-dialog :visible.sync="dialogVisible"> <img width="100%" :src="dialogImageUrl" alt /> </el-dialog> <el-button type="primary" @click="uploadImg"> 點擊上傳 <i class="el-icon-upload el-icon--right"></i> </el-button> <span>{{message}}</span> </div> </template> <script> import http from "../util/http"; export default { data() { return { // 彈出圖片大圖路徑 dialogImageUrl: "", dialogVisible: false, // 存放base64位編碼的圖片集合 base64ImageData: [], message: "當前圖片尚未上傳", }; }, methods: { // 刪除圖片觸發 handleRemove(file, fileList) { // 刪除存放base64位編碼的圖片集合 let removeIndex = this.base64ImageData.findIndex( (item) => file.uid === item.uid ); // 利用findIndex獲取當前刪除的圖片下標 this.base64ImageData.splice(removeIndex, 1); }, // 查看圖片大圖 handlePictureCardPreview(file) { this.dialogImageUrl = file.url; this.dialogVisible = true; }, // 超出最大上傳數量觸發 onExceed() { this.$alert("超出最大上傳數量"); }, // 選擇圖片時觸發 changeIamge(file, fileList) { // 此處調用是選擇圖片就立即轉換為base64 this.getBase64(file.raw).then((res) => { this.base64ImageData.push({ base64Code: res, uid: file.uid, }); }); }, // 將選擇的圖片處理成為Base64 getBase64(file) { // 返回Promise格式 return new Promise((resolve, reject) => { let reader = new FileReader(); let imgResult = ""; reader.readAsDataURL(file); reader.onload = () => { imgResult = reader.result; }; // 成功返回 reader.onloadend = () => { resolve(imgResult); }; // 失敗返回 reader.onerror = () => { reject(error); }; }); }, // 點擊上傳按鈕 async uploadImg() { // 數組非空校驗 if (this.base64ImageData.length === 0) { this.$alert("請選擇圖片再進行上傳操作"); return; } // 存放線上的圖片路徑集合 let resultImage = []; // 利用for of 遍歷依次上傳圖片 entries()可以解決for of 遍歷獲取不到下標的問題 for (const [index, item] of this.base64ImageData.entries()) { let data = { imgName: `圖片_0${index + 1}`, baseCode: item.base64Code, fileName: "jpg", }; // axync await 等待當前循環圖片上傳完成在進行下一張圖片的上傳 let resImage = await this.uploadPostFun(data); // 此狀態嗎和后台商定,成功會返回六個零 if (resImage.code === "000000") { resultImage.push(resImage.result.imgUrl); this.message = `${index + 1}張圖片上傳成功`; } else { this.message = `${index + 1}張圖片上傳失敗`; } } // 在循環外側拿到返回的圖片路徑 console.log(resultImage); }, // 上傳方法,方法成功會返回一個線上的URl圖片路徑 uploadPostFun(data) { return http.post("/fileupload/image", data); }, }, }; </script>
上述代碼中利用 for of 遍歷配合 async await 完美的實現等待調用,返回結果在進行下一次循環
實現的效果如下,選擇圖片點擊上傳
控制台拿到返回的數據
拿到數據后就可以將這些數據給后端,其他頁面請求相關接口查詢地址展示圖片。