大文件分片上傳


1、選擇本地視頻,獲取視頻實體

第一步::auto-upload="false";:on-change="videoSaveToUrl"

<el-upload
action
:auto-upload="false"
:on-change="videoSaveToUrl"
:accept="'video/*'">
</el-upload>

第二步:在videoSaveToUrl方法中獲取視頻實體,並存放在data數據的this.video中

videoSaveToUrl(event) {
  this.video = event.raw;
}

2、單擊“上傳”按鈕,觸發分片上傳方法

//引入uploadByPieces方法
import { uploadByPieces } from "@/utils";

processButtonClick() {
      uploadByPieces({
        file: this.video,//視頻實體
        pieceSize: 5, //分片大小
        success: data => {
          console.log("分片上傳視頻成功");
        },
        error: e => {
          console.log("分片上傳視頻失敗");
        }
      });
    }

3、分片上傳方法(utils.js代碼中的uploadByPieces方法)

第一步:獲取分片上傳過程中會使用到的變量

// 上傳過程中用到的變量
let fileMD5 = ''// 總文件列表  
const chunkSize = pieceSize * 1024 * 1024 // 5MB一片
const chunkCount = Math.ceil(file.size / chunkSize) // 總片數
readFileMD5() // 開始執行代碼

第二步:readFileMD5方法:首先獲取文件的MD5值,並通過網絡請求uploadCheckAxios來檢查是否之前已上傳過該視頻(每個文件的MD5值是唯一的),如果已經上傳過,則后台直接返回視頻在服務器上的URL,如果沒有上傳則進行分片上傳,調用readChunkMD5() 方法

const readFileMD5 = () => {
  // 讀取視頻文件的md5
  console.log("獲取文件的MD5值")
  let fileRederInstance = new FileReader()
  fileRederInstance.readAsBinaryString(file)
  fileRederInstance.addEventListener('load', e => {
    let fileBolb = e.target.result
    fileMD5 = md5(fileBolb)
    uploadCheckAxios({
      "md5": fileMD5
    }).then(res => {
      if (res.data.code == 0) {
        console.log("文件已被上傳")
        console.log(res.data)
        success && success(res)
      } else {
        console.log("文件未被上傳,將分片上傳")
        readChunkMD5()
      }
    }).catch((e) => {
      console.log("文件合並錯誤")
      console.log(e)
    })
  })
}

第三步:readChunkMD5() 方法:分片並上傳,其中uploadChunk為上傳方法

// 針對每個文件進行chunk處理
const readChunkMD5 = () => {
  // 針對單個文件進行chunk上傳
  for (var i = 0; i < chunkCount; i++) {
    const { chunk } = getChunkInfo(file, i, chunkSize)
    console.log("總片數"+chunkCount)
    console.log("分片后的數據---測試:"+i)
    console.log(chunk)
    uploadChunk({ chunk, currentChunk: i, chunkCount })
  }
}
  
// getChunkInfo方法獲取每片視頻
const getChunkInfo = (file, currentChunk, chunkSize) => {
  let start = currentChunk * chunkSize
  let end = Math.min(file.size, start + chunkSize)
  let chunk = file.slice(start, end)
  return { start, end, chunk }
}

第四步:uploadChunk方法:首先分片上傳,上傳完畢后調用后台合並接口

const uploadChunk = (chunkInfo) => {
  let fetchForm = new FormData()
  fetchForm.append('chunk', chunkInfo.currentChunk)
  fetchForm.append('chunkSize', chunkSize)
  fetchForm.append('chunks', chunkInfo.chunkCount)
  fetchForm.append('file', chunkInfo.chunk)
  fetchForm.append('md5', fileMD5)
  fetchForm.append('name', file.name)
  uploadVideoChunkAxios(fetchForm).then(res => {
    console.log("分片上傳返回信息:")
    console.log(res.data)
    if (res.data.code == 0) {
      if (chunkInfo.currentChunk < chunkInfo.chunkCount - 1) {
        console.log("文件分片上傳成功")
      } else {
        // 當總數大於等於分片個數的時候
        if (chunkInfo.currentChunk >= chunkInfo.chunkCount - 1) {
          console.log("文件開始------合並成功")
          //調用合並接口,傳參為視頻文件的額MD5值以及名字
          mergeFileAxios({
            "md5": fileMD5,
            "name": file.name
          }).then(res => {
            if (res.data.code == 0) {
              success && success(res)
              console.log("文件合並成功")
              console.log(res.data.data.url)
            } else {
              console.log(res.data.msg)
            }
          }).catch((e) => {
            console.log("文件合並錯誤")
            console.log(e)
          })
        }
      }
    } else {
      console.log(res.data.msg)
    }
  }).catch((e) => {
    error && error(e)
  })
}

4、utils.js的完整代碼

import md5 from 'js-md5'
import {
  uploadVideoChunkAxios,
  mergeFileAxios,
  uploadCheckAxios
} from '@/api/upload'
export const uploadByPieces = ({
  file,
  pieceSize = 2,
  progress,
  success,
  error
}) => {
  // if (!file || !file.length) return
  // 上傳過程中用到的變量
  let fileMD5 = '' // 總文件列表
  const chunkSize = pieceSize * 1024 * 1024 // 5MB一片
  const chunkCount = Math.ceil(file.size / chunkSize) // 總片數
  // 獲取md5
  const readFileMD5 = () => {
    // 讀取視頻文件的md5
    console.log("獲取文件的MD5值")
    let fileRederInstance = new FileReader()
    fileRederInstance.readAsBinaryString(file)
    fileRederInstance.addEventListener('load', e => {
      let fileBolb = e.target.result
      fileMD5 = md5(fileBolb)
      uploadCheckAxios({
        "md5": fileMD5
      }).then(res => {
        if (res.data.code == 0) {
          console.log("文件已被上傳")
          console.log(res.data)
          success && success(res)
        } else {
          console.log("文件未被上傳,將分片上傳")
          readChunkMD5()
        }
      }).catch((e) => {
        console.log("文件合並錯誤")
        console.log(e)
      })

    })
  }
  const getChunkInfo = (file, currentChunk, chunkSize) => {
    let start = currentChunk * chunkSize
    let end = Math.min(file.size, start + chunkSize)
    let chunk = file.slice(start, end)
    return {
      start,
      end,
      chunk
    }
  }
  // 針對每個文件進行chunk處理
  const readChunkMD5 = () => {
    // 針對單個文件進行chunk上傳
    for (var i = 0; i < chunkCount; i++) {
      const {
        chunk
      } = getChunkInfo(file, i, chunkSize)
      console.log("總片數" + chunkCount)
      console.log("分片后的數據---測試:" + i)
      console.log(chunk)
      uploadChunk({
        chunk,
        currentChunk: i,
        chunkCount
      })
    }
  }
  const uploadChunk = (chunkInfo) => {
    // progressFun()
    let fetchForm = new FormData()
    fetchForm.append('chunk', chunkInfo.currentChunk)
    fetchForm.append('chunkSize', chunkSize)
    fetchForm.append('chunks', chunkInfo.chunkCount)
    fetchForm.append('file', chunkInfo.chunk)
    fetchForm.append('md5', fileMD5)
    fetchForm.append('name', file.name)
    uploadVideoChunkAxios(fetchForm).then(res => {
      console.log("分片上傳返回信息:")
      console.log(res.data)
      if (res.data.code == 0) {
        // success && success(res)
        if (chunkInfo.currentChunk < chunkInfo.chunkCount - 1) {
          console.log("分片上傳成功")
        } else {
          // 當總數大於等於分片個數的時候
          if (chunkInfo.currentChunk >= chunkInfo.chunkCount - 1) {
            console.log("文件開始------合並成功")
            mergeFileAxios({
              "md5": fileMD5,
              "name": file.name
            }).then(res => {
              if (res.data.code == 0) {
                success && success(res)
                console.log("文件合並成功")
                console.log(res.data.data.url)
              } else {
                console.log(res.data.msg)
              }
            }).catch((e) => {
              console.log("文件合並錯誤")
              console.log(e)
            })
          }
        }
      } else {
        console.log(res.data.msg)
      }
    }).catch((e) => {
      error && error(e)
    })
  }
  readFileMD5() // 開始執行代碼
}

說明

uploadVideoChunkAxios 是上傳分片視頻的接口
mergeFileAxios 是合並的接口
uploadCheckAxios 來檢查是否之前已上傳過該視頻


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM