摘要:本文在這里要講的是批量上傳多張圖片時,如果不分批上傳可能觸發瀏覽器的并發限制,亦或是圖片過多過大導致上傳超時,都會影響圖片的上傳成功率。所以,我們需要分批上傳圖片時,概念就能很好的解決我們的問題。
es7提出的async/await概念已經存在有相當長一段時間,具體概念用法就不在這里贅述了,優勢在于處理解決then鏈多層嵌套回調的問題,使得代碼更為簡單清晰。
本文在這里要講的是批量上傳多張圖片時,如果不分批上傳可能觸發瀏覽器的并發限制,亦或是圖片過多過大導致上傳超時,都會影響圖片的上傳成功率。所以,我們需要分批上傳圖片時,async/await概念就能很好的解決我們的問題。否則,就只能使用遞歸來處理,或是只允許單張上傳影響用戶體驗。
其實全部代碼和react沒有太大關系,只是用到部分特性,是可以適用于任何框架的。至于批量獲取圖片的組件我直接用的是react-dropzone,可以拖拽圖片,當然了,使用原生的
也是完全OK的。
預覽代碼
//處理獲取的圖片 handleDropFiles = (acceptedFiles) => { const { maxCount, //最多上傳圖片張數 limit } = this.props; let { selectedFilesTotalSize, selectedFiles } = this.state; const _selectedFiles_ = selectedFiles.map(item => item.file); //已經成功獲取過的圖片 const successFiles = [], //獲取成功的圖片 rejectedFiles = [], //獲取失敗的圖片 existFiles = []; //已經存在的圖片 if (acceptedFiles && acceptedFiles.length) { for (const file of acceptedFiles) { if (limit * 1024 < file.size) { rejectedFiles.push(file); } else { const index = _selectedFiles_.findIndex(acceptedFile => this.isSameFile(file, acceptedFile)); //通過文件名文件大小判斷是否是同一文件 if (index >= 0) { existFiles.push(file); } else { successFiles.push(file); } } } } // 若有不符合條件的圖片輸出錯誤信息 let toastMessage = ""; if (existFiles.length) { const existFilesName = existFiles.map(item => `"${item.name}"`); toastMessage = `${existFilesName.join(", ")}等文件已存在;`; } if (rejectedFiles.length) { const rejectedFilesName = rejectedFiles.map(item => `"${item.name}"`); toastMessage = `${toastMessage}${rejectedFilesName.join(", ")}等文件不符合上傳條件;`; } const incrementLength = successFiles.length; const selectedFilesLength = selectedFiles.length; if (incrementLength + selectedFilesLength > maxCount) { const overflowFiles = successFiles.splice(maxCount - selectedFilesLength); const overflowFilesName = overflowFiles.map(item => `"${item.name}"`); toastMessage = `${toastMessage}${overflowFilesName.join(", ")}等文件超出上傳數量的限制;`; } toastMessage && this.props.onError( toastMessage ); // 多圖預覽 如果只需要用云服務上傳后的url預覽可以將此步驟替換為handleUploadFiles的代碼 if (incrementLength) { // 這里選擇了createObjectURL而不是readAsDataURL具體區別不詳說了 如果要用readAsDataURL還得Promise.all一下 for (const file of successFiles) { const dataUrl = URL.createObjectURL(file); selectedFiles.push({ file, name: file.name, size: file.size, dataUrl, uploadStatus: "beforeUpload" //標識圖片狀態,之后有可能上傳失敗需要重新上傳 }); } selectedFiles = selectedFiles.map((item, index) => return {...item, {index: index}}); selectedFilesTotalSize = selectedFiles.reduce((previousSize, nextFile) => previousSize + nextFile.size, 0); this.setState({ selectedFiles, selectedFilesTotalSize }); } }
批量上傳代碼
// 批量上傳獲取的圖片 handleUploadFiles = async () => { const { batchCount, //一組最多上傳圖片張數(考慮到瀏覽器并發) batchLimit //最多上傳一組圖片大小(考慮到瀏覽器上傳速度限制) } = this.props; const { selectedFiles, uploadedFiles } = this.state; const chunkFiles = chunkFile(selectedFiles.map(file => ["beforeUpload", "failed"].includes(file.uploadStatus))); //根據batchCount&batchLimit給未上傳或上傳失敗的圖片組分塊 const rate = chunkFiles.length; for (const [index, chunkFile] of chunkFiles.entries()) { toast.show(`圖片上傳中${~~(index+1)/rate*100}%`, "loading", this.timeout); //這里做了個假的圖片已上傳率 const uploadFilePromise = chunkFile.map(this.uploadFile); await Promise.all(uploadFilePromise).then((uploadFiles) => { for (const file of uploadFiles) { if ("error" in item) { selectedFiles.find(item => item.index === file.index).uploadStatus = "failed"; //若上傳失敗更改selectedFiles里的圖片狀態 } else { uploadedFiles.push({ url: file.url }); } } }); this.setState({ selectedFiles, uploadedFiles }); this.props.onSuccess(uploadedFiles); } toast.hide(); // 分組上傳 function chunkFile(files) { let array = [], subArray = [], size = 0; files.forEach((item, index) => { size += item.size; if (size > batchLimit*1024 || subArray.length === batchCount) { array.push(subArray); subArray = [item]; size = item.size; } else { subArray.push(item); } if (index === files.length-1) { array.push(subArray); } }); return array; } }
上傳圖片
// ajax上傳單張圖片,就是簡單的FormData隨便看下就好 uploadFile = (file, index) => { return new Promise((resolve, reject) => { const formData = new FormData(); formData.append("file", file); $.ajax(..., (data)=>{ data = (data && data.data) || {}; resolve({ url: data.url, index }); }, (err) => { //this.props.onError(err && err.errMsg || "上傳失敗"); //可以在這根據需求提示第幾張圖片上傳失敗 resolve({ error: err, index }) }, this); }); }
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/107902.html
摘要:異步帶來的問題小程序的網絡請求是異步的我們無法通過來將網絡請求結果返回出來使用。省略其他屬性接業務邏輯代碼例如這個微信的網絡請求,我們可以通過和的回調函數來讀取的值從而完成依賴結果的業務邏輯。 業務邏輯 最近開發一個便簽小程序的時候,有這樣一個需求:用戶可以在寫便簽的時候添加一個或多個圖片。 對于這個需求,我們用戶按下保存鍵時,內部具體的實現上是這樣的邏輯: 首先檢測用戶是否傳入了圖...
摘要:利用中間件實現異步請求,實現兩個用戶角色實時通信。目前還未深入了解的一些概念。往后會寫更多的前后臺聯通的項目。刪除分組會連同組內的所有圖片一起刪除。算是對自己上次用寫后臺的一個強化,項目文章在這里。后來一直沒動,前些日子才把后續的完善。 歡迎訪問我的個人網站:http://www.neroht.com/? 剛學vue和react時,利用業余時間寫的關于這兩個框架的訓練,都相對簡單,有的...
摘要:是一個基于組件的圖片上傳組件支持等服務端自定義獲取簽名批量上傳預覽刪除排序等功能需要版本大于支持地址安裝引入調用圖片上傳服務地址圖片查看地址前綴配置項類型默認值描述類型目前 react-uplod-img 是一個基于 React antd組件的圖片上傳組件 支持oss qiniu等服務端自定義獲取簽名,批量上傳, 預覽, 刪除, 排序等功能 需要 react 版本大于 v16.1.0 ...
閱讀 1379·2023-04-25 18:34
閱讀 3437·2021-11-19 09:40
閱讀 2824·2021-11-17 09:33
閱讀 2935·2021-11-12 10:36
閱讀 2823·2021-09-26 09:55
閱讀 2653·2021-08-05 10:03
閱讀 2512·2019-08-30 15:54
閱讀 2861·2019-08-30 15:54