成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

react利用await/async實(shí)現(xiàn)批量上傳圖片可預(yù)覽可限制上傳圖片數(shù)量

lindroid / 1751人閱讀

摘要:本文在這里要講的是批量上傳多張圖片時(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

相關(guān)文章

  • 小程序異步問(wèn)題:多個(gè)網(wǎng)絡(luò)請(qǐng)求依次執(zhí)行并依次收集請(qǐng)求結(jié)果

    摘要:異步帶來(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è)用戶是否傳入了圖...

    Elle 評(píng)論0 收藏0
  • 一些基于React、Vue、Node.js、MongoDB技術(shù)棧的實(shí)踐項(xiàng)目

    摘要:利用中間件實(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)單,有的...

    tangr206 評(píng)論0 收藏0
  • 分享一個(gè)react 圖片上傳組件 支持OSS 七牛云

    摘要:是一個(gè)基于組件的圖片上傳組件支持等服務(wù)端自定義獲取簽名批量上傳預(yù)覽刪除排序等功能需要版本大于支持地址安裝引入調(diào)用圖片上傳服務(wù)地址圖片查看地址前綴配置項(xiàng)類型默認(rèn)值描述類型目前 react-uplod-img 是一個(gè)基于 React antd組件的圖片上傳組件 支持oss qiniu等服務(wù)端自定義獲取簽名,批量上傳, 預(yù)覽, 刪除, 排序等功能 需要 react 版本大于 v16.1.0 ...

    gself 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<