欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

使用Vue3+ElementPlus前端實(shí)現(xiàn)分片上傳的全過程

 更新時(shí)間:2022年11月08日 10:34:24   作者:Lyrelion  
ElementPlus是一套為開發(fā)者、設(shè)計(jì)師和產(chǎn)品經(jīng)理準(zhǔn)備的基于Vue?3.0的組件庫,提供了配套設(shè)計(jì)資源,幫助你的網(wǎng)站快速成型,下面這篇文章主要給大家介紹了關(guān)于使用Vue3+ElementPlus前端實(shí)現(xiàn)分片上傳的相關(guān)資料,需要的朋友可以參考下

1. 什么是分片上傳

將 一個(gè)文件 切割為 一系列特定大小的 數(shù)據(jù)片段,將這些 數(shù)據(jù)片段 分別上傳到服務(wù)端;

全部上傳完成后,再由服務(wù)端將這些 數(shù)據(jù)片段 合并成為一個(gè)完整的資源;

上傳過程中,由于外部因素(比如網(wǎng)絡(luò)波動(dòng))導(dǎo)致上傳中斷,下次上傳時(shí)會(huì)保留該文件的上傳進(jìn)度(斷點(diǎn)續(xù)傳);

2. 上傳組件模板

包含三部分:

  • 上傳組件,使用 el-upload
  • 進(jìn)度條組件,使用 el-progress
  • 上傳完成狀態(tài)組件,使用 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"
        // 根據(jù)項(xiàng)目的接口傳遞參數(shù)
       :data="{
         applicationId: applicationId,
         applicationVersion: applicationVersion,
         bucketName: 'app'
       }"
       // 覆蓋默認(rèn)的http請(qǐng)求
       :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>
 
     // 進(jìn)度條
     <el-progress
        v-else
        :text-inside="true"
        :stroke-width="24"
        :percentage="progress"
        status="success"
       />
   </el-upload>
 
   // 上傳成功之后隱藏上傳文件組件
   <div v-else style="display: flex;">
     <el-input v-model="editForm.inlineAppVersionModel.fileName" readonly>
     </el-input>
     <div style="display: flex;">
       <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 選擇文件

選擇成功的 回調(diào)函數(shù) 可以讀取文件信息,用于前端校驗(yàn)文件的合法性

前端校驗(yàn)文件合法后,將文件進(jìn)行切片

通過 請(qǐng)求輪詢 把切片傳遞給后端

3.2 選擇上傳文件

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

根據(jù)文件信息,對(duì)文件進(jìn)行合法性校驗(yàn)

校驗(yàn)成功后,調(diào)用文件切片方法

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

3.3 校驗(yàn)文件是否合法

校驗(yàn)文件格式

校驗(yàn)文件大小

調(diào)用接口,校驗(yàn)磁盤剩余空間大小

/**
 * @description: 校驗(yàn)文件合法性
 */
const checkMirrorFile = async (file) => {
    // 校驗(yàn)文件格式,支持.zip/.tar
    const fileType = file.file.name.split('.')
    if (fileType[fileType.length - 1] !== 'zip' && fileType[fileType.length - 1] !== 'tar') {
        ElMessage.warning('文件格式錯(cuò)誤,僅支持 .zip/.tar')
        return false
    }
 
    // 校驗(yàn)文件大小
    const fileSize = file.file.size;
    // 文件大小是否超出 2G
    if (fileSize > 2 * 1024 * 1024 * 1024) {
        ElMessage.warning('上傳文件大小不能超過 2G')
        return false
    }
 
    // 調(diào)用接口校驗(yàn)文件合法性,比如判斷磁盤空間大小是否足夠
    const res = await checkMirrorFileApi()
    if (res.code !== 200) {
        ElMessage.warning('暫時(shí)無法查看磁盤可用空間,請(qǐng)重試')
        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,轉(zhuǎn)為字節(jié)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 進(jìn)行加密,需要安裝依賴 spark-md5

npm i spark-md5

/**
 * @description: 文件加密處理
 */
const getMD5 = (file: any): Promise<string> => new Promise((resolve, reject) => {
  const spark = new SparkMD5.ArrayBuffer();
  // 獲取文件二進(jìn)制數(shù)據(jù)
  const fileReader = new FileReader();
  fileReader.readAsArrayBuffer(file); // file 就是獲取到的文件
  // 異步執(zhí)行函數(shù)
  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 合并文件

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

  • 文件名
  • 文件唯一 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) {
    // 合并成功后,調(diào)整已上傳的文件名稱
    state.editForm.inlineAppVersionModel.fileName = name;
  }
};

3.6 文件切片上傳

接口輪詢 —— 每次攜帶一個(gè)文件切片給后端;后端接受到切片 并 返回成功狀態(tài)碼后,再進(jìn)行下一次切片上傳

/**
 * @description: 分片函數(shù)
 * @param file 文件
 * @param shardIndex 分片數(shù)量
 */
const uploadFileSilce = async (file: File, shardIndex: number) => {
      // 文件名
      const { name } = file;
      // 文件大小
      const { size } = file;
      // 分片大小
      const shardSize = 1024 * 1024 * 5;
      // 文件加密
      const hash: string = await getMD5(file);
      // 分片總數(shù)
      const shardTotal = Math.ceil(size / shardSize);
 
      // 如果 當(dāng)前分片索引 大于 總分片數(shù)
      if (shardIndex >= shardTotal) {
        isAlive.value = false;
        progress.value = 100;
        // 合并文件
        composeFile(name, hash);
        return;
      }
 
      // 文件開始結(jié)束的位置
      const start = shardIndex * shardSize;
      const end = Math.min(start + shardSize, size);
      // 開始切割
      const packet = file.slice(start, end);
      
      // 拼接請(qǐng)求參數(shù)
      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);
 
      // 如果 當(dāng)前分片索引 小于 總分片數(shù)
      if (shardIndex < shardTotal) {
        // 進(jìn)度條保留兩位小數(shù)展示
        progress.value = Number(((shardIndex / shardTotal) * 100).toFixed(2)) * 1;
        // 調(diào)用文件上傳接口
        const res = await uploadFile(formData);
        if (res.status !== 200) {
          ElMessage.error('上傳失敗');
          progress.value = 0;
          return;
        }
        if (res.status === 200 && res.data.code === 200) {
          // 這里為所有切片上傳成功后進(jìn)行的操作
          console.log('上傳成功');
        }
        // eslint-disable-next-line no-param-reassign
        shardIndex++;
        // 遞歸調(diào)用 分片函數(shù)
        uploadFileSilce(file, shardIndex);
      }
    };

4. 參考文章

4.1 文章鏈接

前端大文件上傳和下載(分片上傳)

4.2 參考文章提到的注意事項(xiàng)

4.2.1 nginx 上傳大小限制

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

4.2.2 大文件下載

/**
 * @description: 動(dòng)態(tài)創(chuàng)建 a 標(biāo)簽,實(shí)現(xiàn)大文件下載
 */
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)
    // 通過創(chuàng)建a標(biāo)簽實(shí)現(xiàn)文件下載
    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',
    })
  }
}

總結(jié)

到此這篇關(guān)于使用Vue3+ElementPlus前端實(shí)現(xiàn)分片上傳的文章就介紹到這了,更多相關(guān)Vue3+ElementPlus前端分片上傳內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • vue中的主動(dòng)觸發(fā)點(diǎn)擊事件

    vue中的主動(dòng)觸發(fā)點(diǎn)擊事件

    這篇文章主要介紹了vue中的主動(dòng)觸發(fā)點(diǎn)擊事件,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-04-04
  • vue項(xiàng)目部署自動(dòng)清除緩存方式

    vue項(xiàng)目部署自動(dòng)清除緩存方式

    這篇文章主要介紹了vue項(xiàng)目部署自動(dòng)清除緩存方式,包括清除文件緩存,清除瀏覽器 localStorage 緩存方式,本文結(jié)合示例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2023-07-07
  • vue3?element?plus?table?selection展示數(shù)據(jù),默認(rèn)選中功能方式

    vue3?element?plus?table?selection展示數(shù)據(jù),默認(rèn)選中功能方式

    這篇文章主要介紹了vue3?element?plus?table?selection展示數(shù)據(jù),默認(rèn)選中功能方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-07-07
  • vue實(shí)現(xiàn)2048小游戲功能思路詳解

    vue實(shí)現(xiàn)2048小游戲功能思路詳解

    這篇文章主要介紹了vue實(shí)現(xiàn)2048小游戲功能,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2018-05-05
  • Windows系統(tǒng)下使用nginx部署vue2項(xiàng)目的全過程

    Windows系統(tǒng)下使用nginx部署vue2項(xiàng)目的全過程

    nginx是一個(gè)高性能的HTTP和反向代理服務(wù)器,因此常用來做靜態(tài)資源服務(wù)器和后端的反向代理服務(wù)器,下面這篇文章主要給大家介紹了關(guān)于Windows系統(tǒng)下使用nginx部署vue2項(xiàng)目的相關(guān)資料,需要的朋友可以參考下
    2023-03-03
  • vue組件之全局注冊(cè)和局部注冊(cè)方式

    vue組件之全局注冊(cè)和局部注冊(cè)方式

    這篇文章主要介紹了vue組件之全局注冊(cè)和局部注冊(cè)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-03-03
  • Vue.js 插件開發(fā)詳解

    Vue.js 插件開發(fā)詳解

    本文會(huì)通過一個(gè)簡(jiǎn)單的vue-toast插件,來幫助了解掌握插件的開發(fā)和使用。具有很好的參考價(jià)值,下面跟著小編一起來看下吧
    2017-03-03
  • vue3.2?Composition?API項(xiàng)目依賴升級(jí)

    vue3.2?Composition?API項(xiàng)目依賴升級(jí)

    這篇文章主要為大家介紹了vue3.2?Composition?API項(xiàng)目依賴升級(jí)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08
  • Vue實(shí)現(xiàn)簡(jiǎn)易購物車案例

    Vue實(shí)現(xiàn)簡(jiǎn)易購物車案例

    這篇文章主要為大家詳細(xì)介紹了Vue實(shí)現(xiàn)簡(jiǎn)易購物車案例,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-06-06
  • vue配置別名alias在webstorm不生效問題及解決

    vue配置別名alias在webstorm不生效問題及解決

    這篇文章主要介紹了vue配置別名alias在webstorm不生效問題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-10-10

最新評(píng)論