大文件分片上传

摘要:
1、选择本地视频,获取视频实体第一步::auto-upload="false";:on-change="videoSaveToUrl"第二步:在videoSaveToUrl方法中获取视频实体,并存放在data数

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 来检查是否之前已上传过该视频

免责声明:文章转载自《大文件分片上传》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇生产者和消费者模型Redis分布式锁实战下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

简单自定义控件在view下可以运行在传统模式下运行显示空白

简单自定义控件-在view下可以运行-在传统模式下运行显示空白 问题描述 我写了一个自定义的控件头文件 #include <coecntrl.h>class CSimControl : public CCoeControl  {public:    static CSimControl* NewL(const TRect& aRect...

ant design vue 获取上传图片的像素

获取图片的像素大小,使用上传文件之前的钩子 beforeUpload,参数为上传的文件。 <a-upload name="file" list-type="picture-card" :show-upload-list="false" :multiple="false" :b...

从零开始配置TypeScript + React + React-Router + Redux + Webpack开发环境

转载请注明出处! 说在前面的话: 1、为什么不使用现成的脚手架?脚手架配置的东西太多太重了,一股脑全塞给你,我只想先用一些我能懂的库和插件,然后慢慢的添加其他的。而且自己从零开始配置也能学到更多的东西不是么。 2、教程只配置了开发环境,并没有配置生产环境。 3、教程针对人群是有过React + Redux经验,并且想在新项目中使用TypeScript的人(...

PCRE函数简介和使用示例

PCRE是一个NFA正则引擎,不然不能提供完全与Perl一致的正则语法功能。但它同时也实现了DFA,只是满足数学意义上的正则。 PCRE提供了19个接口函数,为了简单介绍,使用PCRE内带的测试程序(pcretest.c)示例用法。 pcre_compile原型:#include <pcre.h>pcre *pcre_compile(cons...

QT分析之WebKit(三)

QT分析之WebKit(三) 分三个阶段对QWebView进行分析:初始化(获取数据)、HTML解析、页面显示。从QT自带的文档中可以知道: QWebView -> QWebPage => QWebFrame(一个QWebPage含多个QWebFrame) 在界面中选择了Open URL,输入URL之后,调用的是:void MainWindo...

POJ 3281 Dining (网络流之最大流)

题意:农夫为他的 N (1 ≤ N ≤ 100) 牛准备了 F (1 ≤ F ≤ 100)种食物和 D (1 ≤ D ≤ 100) 种饮料。每头牛都有各自喜欢的食物和饮料, 而每种食物或饮料只能分配给一头牛。最多能有多少头牛可以同时得到喜欢的食物和饮料? 析:是一个经典网络流的题,建立一个超级源点,连向每种食物,建立一个超级汇点,连向每种饮料,然后把每头牛...