• 大文件分片上传


    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 来检查是否之前已上传过该视频
  • 相关阅读:
    使用SuperWebSocket 构建实时 Web 应用
    slam for Windows 库安装及应用libfreenect2
    《SLAM十四讲》g2o_custombundle在windows轻松调通
    windows下命令行查看库依赖
    zend studio控制台中文乱码
    http协议转
    mysql 字段 增删改
    PHP内部函数
    分层设计
    SecureCRT上传和下载
  • 原文地址:https://www.cnblogs.com/HanJie0824/p/15704883.html
Copyright © 2020-2023  润新知