摘要:本文在這里要講的是批量上傳多張圖片時(shí),如果不分批上傳可能觸發(fā)瀏覽器的并發(fā)限制,亦或是圖片過(guò)多過(guò)大導(dǎo)致上傳超時(shí),都會(huì)影響圖片的上傳成功率。所以,我們需要分批上傳圖片時(shí),概念就能很好的解決我們的問(wèn)題。
es7提出的async/await概念已經(jīng)存在有相當(dāng)長(zhǎng)一段時(shí)間,具體概念用法就不在這里贅述了,優(yōu)勢(shì)在于處理解決then鏈多層嵌套回調(diào)的問(wèn)題,使得代碼更為簡(jiǎn)單清晰。
本文在這里要講的是批量上傳多張圖片時(shí),如果不分批上傳可能觸發(fā)瀏覽器的并發(fā)限制,亦或是圖片過(guò)多過(guò)大導(dǎo)致上傳超時(shí),都會(huì)影響圖片的上傳成功率。所以,我們需要分批上傳圖片時(shí),async/await概念就能很好的解決我們的問(wèn)題。否則,就只能使用遞歸來(lái)處理,或是只允許單張上傳影響用戶體驗(yàn)。
其實(shí)全部代碼和react沒(méi)有太大關(guān)系,只是用到部分特性,是可以適用于任何框架的。至于批量獲取圖片的組件我直接用的是react-dropzone,可以拖拽圖片,當(dāng)然了,使用原生的
也是完全OK的。
預(yù)覽代碼
//處理獲取的圖片 handleDropFiles = (acceptedFiles) => { const { maxCount, //最多上傳圖片張數(shù) limit } = this.props; let { selectedFilesTotalSize, selectedFiles } = this.state; const _selectedFiles_ = selectedFiles.map(item => item.file); //已經(jīng)成功獲取過(guò)的圖片 const successFiles = [], //獲取成功的圖片 rejectedFiles = [], //獲取失敗的圖片 existFiles = []; //已經(jīng)存在的圖片 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)); //通過(guò)文件名文件大小判斷是否是同一文件 if (index >= 0) { existFiles.push(file); } else { successFiles.push(file); } } } } // 若有不符合條件的圖片輸出錯(cuò)誤信息 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(", ")}等文件超出上傳數(shù)量的限制;`; } toastMessage && this.props.onError( toastMessage ); // 多圖預(yù)覽 如果只需要用云服務(wù)上傳后的url預(yù)覽可以將此步驟替換為handleUploadFiles的代碼 if (incrementLength) { // 這里選擇了createObjectURL而不是readAsDataURL具體區(qū)別不詳說(shuō)了 如果要用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" //標(biāo)識(shí)圖片狀態(tài),之后有可能上傳失敗需要重新上傳 }); } 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, //一組最多上傳圖片張數(shù)(考慮到瀏覽器并發(fā)) batchLimit //最多上傳一組圖片大?。紤]到瀏覽器上傳速度限制) } = this.props; const { selectedFiles, uploadedFiles } = this.state; const chunkFiles = chunkFile(selectedFiles.map(file => ["beforeUpload", "failed"].includes(file.uploadStatus))); //根據(jù)batchCount&batchLimit給未上傳或上傳失敗的圖片組分塊 const rate = chunkFiles.length; for (const [index, chunkFile] of chunkFiles.entries()) { toast.show(`圖片上傳中${~~(index+1)/rate*100}%`, "loading", this.timeout); //這里做了個(gè)假的圖片已上傳率 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里的圖片狀態(tài) } 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上傳單張圖片,就是簡(jiǎn)單的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 || "上傳失敗"); //可以在這根據(jù)需求提示第幾張圖片上傳失敗 resolve({ error: err, index }) }, this); }); }
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/107902.html
摘要:異步帶來(lái)的問(wèn)題小程序的網(wǎng)絡(luò)請(qǐng)求是異步的我們無(wú)法通過(guò)來(lái)將網(wǎng)絡(luò)請(qǐng)求結(jié)果返回出來(lái)使用。省略其他屬性接業(yè)務(wù)邏輯代碼例如這個(gè)微信的網(wǎng)絡(luò)請(qǐng)求,我們可以通過(guò)和的回調(diào)函數(shù)來(lái)讀取的值從而完成依賴結(jié)果的業(yè)務(wù)邏輯。 業(yè)務(wù)邏輯 最近開(kāi)發(fā)一個(gè)便簽小程序的時(shí)候,有這樣一個(gè)需求:用戶可以在寫便簽的時(shí)候添加一個(gè)或多個(gè)圖片。 對(duì)于這個(gè)需求,我們用戶按下保存鍵時(shí),內(nèi)部具體的實(shí)現(xiàn)上是這樣的邏輯: 首先檢測(cè)用戶是否傳入了圖...
摘要:利用中間件實(shí)現(xiàn)異步請(qǐng)求,實(shí)現(xiàn)兩個(gè)用戶角色實(shí)時(shí)通信。目前還未深入了解的一些概念。往后會(huì)寫更多的前后臺(tái)聯(lián)通的項(xiàng)目。刪除分組會(huì)連同組內(nèi)的所有圖片一起刪除。算是對(duì)自己上次用寫后臺(tái)的一個(gè)強(qiáng)化,項(xiàng)目文章在這里。后來(lái)一直沒(méi)動(dòng),前些日子才把后續(xù)的完善。 歡迎訪問(wèn)我的個(gè)人網(wǎng)站:http://www.neroht.com/? 剛學(xué)vue和react時(shí),利用業(yè)余時(shí)間寫的關(guān)于這兩個(gè)框架的訓(xùn)練,都相對(duì)簡(jiǎn)單,有的...
摘要:是一個(gè)基于組件的圖片上傳組件支持等服務(wù)端自定義獲取簽名批量上傳預(yù)覽刪除排序等功能需要版本大于支持地址安裝引入調(diào)用圖片上傳服務(wù)地址圖片查看地址前綴配置項(xiàng)類型默認(rèn)值描述類型目前 react-uplod-img 是一個(gè)基于 React antd組件的圖片上傳組件 支持oss qiniu等服務(wù)端自定義獲取簽名,批量上傳, 預(yù)覽, 刪除, 排序等功能 需要 react 版本大于 v16.1.0 ...
閱讀 1437·2023-04-25 18:34
閱讀 3547·2021-11-19 09:40
閱讀 2853·2021-11-17 09:33
閱讀 3001·2021-11-12 10:36
閱讀 2866·2021-09-26 09:55
閱讀 2683·2021-08-05 10:03
閱讀 2548·2019-08-30 15:54
閱讀 2895·2019-08-30 15:54