当前位置:   article > 正文

vue 大文件视频切片上传处理方法_vue上传视频

vue上传视频

前端上传大文件、视频的时候会出现超时、过大、很慢等情况,为了解决这一问题,跟后端配合做了一个切片的功能。

我这个切片功能是基于 minion 的,后端会把文件放在minion服务器上。具体看后端怎么做

1、在项目的 util(这个文件夹是自己创建的,如果项目里没有可以自行创建) 文件家中创建一个js文件 upload.js   在js文件中添加如下代码:

  1. import axios from 'axios';
  2. import md5 from 'js-md5' //引入MD5加密
  3. export const uploadByPieces = ({ urlList, file, pieceSize, progress, beforeSuccess, success, error }) => {
  4. // 如果文件传入为空直接 return 返回
  5. if (!file) return
  6. let fileMD5 = ''// 总文件列表
  7. const chunkSize = pieceSize * 1024 * 1024 // 5MB一片
  8. const chunkCount = Math.ceil(file.size / chunkSize - 1) // 总片数
  9. // 获取md5
  10. const readFileMD5 = () => {
  11. // 读取视频文件的md5
  12. // console.log("获取文件的MD5值")
  13. let fileRederInstance = new FileReader()
  14. // console.log('file', file)
  15. fileRederInstance.readAsBinaryString(file)
  16. fileRederInstance.addEventListener('load', e => {
  17. let fileBolb = e.target.result
  18. fileMD5 = md5(fileBolb)
  19. // console.log('fileMD5', fileMD5)
  20. // console.log("文件未被上传,将分片上传")
  21. readChunkMD5()
  22. })
  23. }
  24. const getChunkInfo = (file, currentChunk, chunkSize) => {
  25. let start = currentChunk * chunkSize
  26. let end = Math.min(file.size, start + chunkSize)
  27. let chunk = file.slice(start, end)
  28. return { start, end, chunk }
  29. }
  30. // 针对每个文件进行chunk处理
  31. const readChunkMD5 = () => {
  32. // 针对单个文件进行chunk上传
  33. for (var i = 0; i < chunkCount; i++) {
  34. const { chunk } = getChunkInfo(file, i, chunkSize)
  35. // console.log("切片地址123" + urlList)
  36. // console.log("总片数" + chunkCount)
  37. // console.log("分片后的数据---测试:" + i)
  38. // console.log(chunk)
  39. let fileUrl = urlList[i];
  40. // console.log(fileUrl,'地址');
  41. uploadChunk({ chunk, currentChunk: i, chunkCount, fileUrl })
  42. }
  43. }
  44. const uploadChunk = (chunkInfo) => {
  45. // 上传请求方式1 (根据自身情况自行选择)
  46. // console.log(chunkInfo.chunk,'chunkInfochunkInfo');
  47. let files = chunkInfo.chunk
  48. axios.put(chunkInfo.fileUrl,files).then((res) => {
  49. // console.log("分片上传返回信息:"+ res)
  50. if (res.status == 200) {
  51. // 下面如果在项目中没有用到可以不用打开注释
  52. if (chunkInfo.currentChunk < chunkInfo.chunkCount - 1) {
  53. beforeSuccess()
  54. } else {
  55. // 当总数大于等于分片个数的时候
  56. if ((chunkInfo.currentChunk + 1) == chunkInfo.chunkCount) {
  57. // console.log("文件开始------合并成功")
  58. success(res.data[0])
  59. }
  60. }
  61. }
  62. }).catch((e) => {
  63. console.log('失败!');
  64. error && error(e)
  65. })
  66. }
  67. readFileMD5() // 开始执行代码
  68. }

js-md5 如果没有的话需要自己在项目里安装:

npm install js-md5

2、创建一个上传视频文件的公共组件,便于不同地方引用,如下:

  1. <template>
  2. <div class="container" style="display:inline-block;width: 200px;">
  3. <el-upload
  4. class="upload-demo"
  5. action="#"
  6. :multiple="false"
  7. :auto-upload="false"
  8. accept=".mp4"
  9. :on-change="handleChange"
  10. :show-file-list="false">
  11. <el-button slot="trigger" size="small" type="primary" :disabled="isUploadVideo">选择视频</el-button>
  12. <!-- <el-button size="small" type="primary" @click="uploadVideo()" style="margin-left: 10px;">开始上传</el-button> -->
  13. </el-upload>
  14. <!-- 进度条 -->
  15. <el-progress v-if="progressFlag" :percentage="loadProgress"></el-progress>
  16. </div>
  17. </template>
  18. <script>
  19. import {mapGetters} from "vuex";
  20. import { uploadByPieces } from '@/util/upload-video'
  21. import api from "@/api/mes2/index-lhj"
  22. export default {
  23. data() {
  24. return {
  25. isUploadVideo: false,
  26. uploadId: '', // 切片视频的唯一id(后端返回)
  27. fileNameVal: '', // 文件名称(后端返回)
  28. listUrl: [], // 切片路径集合
  29. loadProgress: 0, // 动态显示进度条
  30. progressFlag: false, // 关闭进度条
  31. }
  32. },
  33. created(){
  34. },
  35. computed: {
  36. ...mapGetters(["userInfo"]),
  37. },
  38. props:{
  39. paramsData: {
  40. type: Object,
  41. default: {}
  42. }
  43. },
  44. methods: {
  45. // 选择视频
  46. handleChange(file, fileList) {
  47. this.isUploadVideo = true;
  48. this.progressFlag = true; // 显示进度条
  49. this.loadProgress = 10; // 动态获取文件上传进度
  50. let fileSizeVal = file.size / 1024 / 1024;
  51. let numVal = null;
  52. if(fileSizeVal <= 20){
  53. numVal = 1;
  54. }else{
  55. numVal = Math.ceil(file.size / (10 * 1024 * 1024));
  56. }
  57. let params = {
  58. fileName: file.name,
  59. partCount: numVal - 1,
  60. tenantId: this.userInfo.tenant_id,
  61. fileType: "mp4",
  62. fileSize: file.size,
  63. sourceId: this.paramsData.id,
  64. sourceType: this.paramsData.inspectionType,
  65. sourceSystem: "MES2",
  66. hierarchyCode:"MES2"
  67. }
  68. api.queryUploadBigFileUrl(params).then((res) => {
  69. this.loadProgress = 20;
  70. this.listUrl = res.data.data.partUrlList;
  71. this.uploadId = res.data.data.uploadId;
  72. this.fileNameVal = res.data.data.fileName
  73. // 调用切片方法
  74. uploadByPieces({
  75. urlList: this.listUrl,
  76. file: file.raw, // 视频实体
  77. pieceSize: 10, // 分片大小
  78. beforeSuccess: data => {
  79. // 进度数 / 切片总数
  80. let progress = Math.floor(70 / (numVal - 1)); // 计算进度
  81. this.loadProgress += progress;
  82. },
  83. success: data => {
  84. // console.log('分片上传视频成功', data)
  85. this.getFileAll(numVal)
  86. },
  87. error: e => {
  88. console.log('分片上传视频失败', e)
  89. this.$message.error('视频切片上传失败,请重新上传!')
  90. this.progressFlag = false
  91. }
  92. })
  93. }).catch(() => {
  94. this.$message.error('发生错误,请重新上传!')
  95. this.progressFlag = false
  96. })
  97. },
  98. // 整合切片文件
  99. getFileAll(numVal){
  100. let params = {
  101. partCount: numVal - 1,
  102. tenantId: this.userInfo.tenant_id,
  103. uploadId: this.uploadId,
  104. fileName: this.fileNameVal,
  105. }
  106. this.loadProgress = 95;
  107. api.queryUploadBigFile(params).then((res) => {
  108. if(res.data.data === false){
  109. this.isUploadVideo = false;
  110. this.$message.error('视频切片合并失败,请重新上传!')
  111. setTimeout( () => {this.progressFlag = false}, 1000) // 一秒后关闭进度条
  112. }else{
  113. this.loadProgress = 100;
  114. this.isUploadVideo = false;
  115. this.$message.success('视频上传成功!')
  116. this.$emit('uploadVideoData');
  117. if (this.loadProgress >= 100) {
  118. this.loadProgress = 100
  119. setTimeout( () => {this.progressFlag = false}, 1000) // 一秒后关闭进度条
  120. }
  121. }
  122. }).catch(() => {
  123. this.isUploadVideo = false;
  124. this.$message.error('视频合并上传失败,请重新上传!')
  125. })
  126. },
  127. },
  128. }
  129. </script>
  130. <style scoped lang="scss">
  131. </style>

具体根据自己的实际情况进行修改即可!

至此完成!!!

测试有效!!!感谢支持!!!

本文内容由网友自发贡献,转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/267818
推荐阅读
相关标签
  

闽ICP备14008679号