亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何使用Vue3和ElementPlus前端實現分片上傳

發布時間:2022-11-09 09:19:03 來源:億速云 閱讀:243 作者:iii 欄目:開發技術

這篇文章主要講解了“如何使用Vue3和ElementPlus前端實現分片上傳”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“如何使用Vue3和ElementPlus前端實現分片上傳”吧!

    1. 什么是分片上傳

    將 一個文件 切割為 一系列特定大小的 數據片段,將這些 數據片段 分別上傳到服務端;

    全部上傳完成后,再由服務端將這些 數據片段 合并成為一個完整的資源;

    上傳過程中,由于外部因素(比如網絡波動)導致上傳中斷,下次上傳時會保留該文件的上傳進度(斷點續傳);

    2. 上傳組件模板

    包含三部分:

    • 上傳組件,使用 el-upload

    • 進度條組件,使用 el-progress

    • 上傳完成狀態組件,使用 el-input 自定義

     <el-form-item label="上傳附件" prop="uploadFile">
       <el-upload
           v-if="!editForm.inlineAppVersionModel.fileName"
           class="upload-demo"
           drag
           :show-file-list="false"
           :action="APP_MANAGEMENT.uploadFile"
            // 根據項目的接口傳遞參數
           :data="{
             applicationId: applicationId,
             applicationVersion: applicationVersion,
             bucketName: 'app'
           }"
           // 覆蓋默認的http請求
           :http-request="handleFileUpload"
       >
         <el-icon class="el-icon--upload">
           <upload-filled />
         </el-icon>
     
         <div v-if="!progress" class="el-upload__text">
           Drop file here or <em>click to upload</em>
         </div>
     
         // 進度條
         <el-progress
            v-else
            :text-inside="true"
            :stroke-width="24"
            :percentage="progress"
            status="success"
           />
       </el-upload>
     
       // 上傳成功之后隱藏上傳文件組件
       <div v-else >
         <el-input v-model="editForm.inlineAppVersionModel.fileName" readonly>
         </el-input>
         <div >
           <el-button 
               type="primary" 
               :icon="Download" 
               size="small" 
               @click="handleFileDownload" 
              />
           <el-button type="primary" :icon="Delete" size="small" @click="handleFileDel" />
         </div>
       </div>
     </el-form-item>

    3. 上傳組件邏輯

    3.1 基本思路

    使用 el-upload 選擇文件

    選擇成功的 回調函數 可以讀取文件信息,用于前端校驗文件的合法性

    前端校驗文件合法后,將文件進行切片

    通過 請求輪詢 把切片傳遞給后端

    3.2 選擇上傳文件

    在這一步,可以獲得文件信息

    根據文件信息,對文件進行合法性校驗

    校驗成功后,調用文件切片方法

    /**
     * @description: 選擇上傳文件
     * @param file el-upload 返回的參數
     */
    const handleFileUpload = async (file: any) => {
      console.log('el-upload 返回的參數 === ', file.file);
     
      // 如果文件合法,則進行分片上傳
      if (await checkMirrorFile(file)) {
        // 文件信息
        const files = file.file;
        // 從 0 開始的切片
        const shardIndex = 0;
        // 調用 文件切片 方法
        uploadFileSilce(files, shardIndex);
      // 文件非法,則進行提示
      } else {
        ElMessage.error('請檢查文件是否合法!');
      }
    };

    3.3 校驗文件是否合法

    校驗文件格式

    校驗文件大小

    調用接口,校驗磁盤剩余空間大小

    /**
     * @description: 校驗文件合法性
     */
    const checkMirrorFile = async (file) => {
        // 校驗文件格式,支持.zip/.tar
        const fileType = file.file.name.split('.')
        if (fileType[fileType.length - 1] !== 'zip' && fileType[fileType.length - 1] !== 'tar') {
            ElMessage.warning('文件格式錯誤,僅支持 .zip/.tar')
            return false
        }
     
        // 校驗文件大小
        const fileSize = file.file.size;
        // 文件大小是否超出 2G
        if (fileSize > 2 * 1024 * 1024 * 1024) {
            ElMessage.warning('上傳文件大小不能超過 2G')
            return false
        }
     
        // 調用接口校驗文件合法性,比如判斷磁盤空間大小是否足夠
        const res = await checkMirrorFileApi()
        if (res.code !== 200) {
            ElMessage.warning('暫時無法查看磁盤可用空間,請重試')
            return false
        }
        // 查看磁盤容量大小
        if (res.data.diskDevInfos && res.data.diskDevInfos.length > 0) {
            let saveSize = 0
            res.data.diskDevInfos.forEach(i => {
                // 磁盤空間賦值
                if (i.devName === '/dev/mapper/centos-root') {
                    // 返回值為GB,轉為字節B
                    saveSize = i.free * 1024 * 1024 * 1024
                }
            })
            // 上傳的文件大小沒有超出磁盤可用空間
            if (fileSize < saveSize) {
                return true
            } else {
                ElMessage.warning('文件大小超出磁盤可用空間容量')
                return false
            }
        } else {
            ElMessage.warning('文件大小超出磁盤可用空間容量')
            return false
        }
    }

    3.4 文件加密

    此處文件上傳用 MD5 進行加密,需要安裝依賴 spark-md5

    npm i spark-md5

    /**
     * @description: 文件加密處理
     */
    const getMD5 = (file: any): Promise<string> => new Promise((resolve, reject) => {
      const spark = new SparkMD5.ArrayBuffer();
      // 獲取文件二進制數據
      const fileReader = new FileReader();
      fileReader.readAsArrayBuffer(file); // file 就是獲取到的文件
      // 異步執行函數
      fileReader.addEventListener('load', (e: any) => {
        spark.append(e.target.result);
        const md5: string = spark.end();
        resolve(md5);
      });
      fileReader.addEventListener('error', (e) => {
        reject(e);
      });
    });

    3.5 合并文件

    通過接口合并上傳文件,接口需要的參數:

    • 文件名

    • 文件唯一 hash 值

    接口合并完成后,前端展示已上傳的文件名稱

    /**
     * @description: 合并文件
     * @param name 文件名
     * @param hash 文件唯一 hash 值
     * @return 命名名稱
     */
    const composeFile = async (name: string, hash: string) => {
      console.log('開始文件合并');
      const res = await uploadFileMerge({
        applicationId: props.applicationId,
        applicationVersion: props.applicationVersion,
        bucketName: 'app',
        fileName: name,
        hash,
      });
      console.log('后端接口合并文件 ===', res);
      if (res.status === 200 && res.data.code) {
        // 合并成功后,調整已上傳的文件名稱
        state.editForm.inlineAppVersionModel.fileName = name;
      }
    };

    3.6 文件切片上傳

    接口輪詢 &mdash;&mdash; 每次攜帶一個文件切片給后端;后端接受到切片 并 返回成功狀態碼后,再進行下一次切片上傳

    /**
     * @description: 分片函數
     * @param file 文件
     * @param shardIndex 分片數量
     */
    const uploadFileSilce = async (file: File, shardIndex: number) => {
          // 文件名
          const { name } = file;
          // 文件大小
          const { size } = file;
          // 分片大小
          const shardSize = 1024 * 1024 * 5;
          // 文件加密
          const hash: string = await getMD5(file);
          // 分片總數
          const shardTotal = Math.ceil(size / shardSize);
     
          // 如果 當前分片索引 大于 總分片數
          if (shardIndex >= shardTotal) {
            isAlive.value = false;
            progress.value = 100;
            // 合并文件
            composeFile(name, hash);
            return;
          }
     
          // 文件開始結束的位置
          const start = shardIndex * shardSize;
          const end = Math.min(start + shardSize, size);
          // 開始切割
          const packet = file.slice(start, end);
          
          // 拼接請求參數
          const formData = new FormData();
          formData.append('file', packet);
          formData.append('applicationId', props.applicationId);
          formData.append('applicationVersion', props.applicationVersion);
          formData.append('bucketName', 'app');
          formData.append('hash', hash);
          formData.append('shardSize', shardSize as unknown as string);
          formData.append('seq', shardIndex as unknown as string);
     
          // 如果 當前分片索引 小于 總分片數
          if (shardIndex < shardTotal) {
            // 進度條保留兩位小數展示
            progress.value = Number(((shardIndex / shardTotal) * 100).toFixed(2)) * 1;
            // 調用文件上傳接口
            const res = await uploadFile(formData);
            if (res.status !== 200) {
              ElMessage.error('上傳失敗');
              progress.value = 0;
              return;
            }
            if (res.status === 200 && res.data.code === 200) {
              // 這里為所有切片上傳成功后進行的操作
              console.log('上傳成功');
            }
            // eslint-disable-next-line no-param-reassign
            shardIndex++;
            // 遞歸調用 分片函數
            uploadFileSilce(file, shardIndex);
          }
        };
    4、nginx 上傳大小限制

    nginx 默認上傳大小為 1MB,若超過 1MB,則需要修改 nginx 配置 解除上傳限制

    5、 大文件下載
    /**
     * @description: 動態創建 a 標簽,實現大文件下載
     */
    const downloadMirror = async (item) => {
      let t = {
        id: item.id,
      }
      const res = await downloadMirrorApi(t)
      if (res.headers["content-disposition"]) {
        let temp = res.headers["content-disposition"].split(";")[1].split("filename=")[1]
        let fileName = decodeURIComponent(temp)
        // 通過創建a標簽實現文件下載
        let link = document.createElement('a')
        link.download = fileName
        link.style.display = 'none'
        link.href = res.data.msg
        document.body.appendChild(link)
        link.click()
        document.body.removeChild(link)
      } else {
        ElMessage({
          message: '該文件不存在',
          type: 'warning',
        })
      }
    }

    感謝各位的閱讀,以上就是“如何使用Vue3和ElementPlus前端實現分片上傳”的內容了,經過本文的學習后,相信大家對如何使用Vue3和ElementPlus前端實現分片上傳這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!

    向AI問一下細節

    免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

    AI

    永宁县| 大理市| 辽中县| 浠水县| 湘潭市| 定兴县| 静海县| 陆川县| 奉贤区| 道真| 库尔勒市| 五原县| 长宁县| 泽普县| 兰溪市| 囊谦县| 韶关市| 平泉县| 灌云县| 富阳市| 丹棱县| 西畴县| 柳江县| 汨罗市| 泗水县| 濮阳县| 措美县| 额尔古纳市| 武城县| 通河县| 三都| 镇康县| 昌图县| 阿勒泰市| 合江县| 定陶县| 临西县| 建始县| 永清县| 阜南县| 崇阳县|