首页 > 其他分享 >详解vue大文件视频切片上传的处理方法

详解vue大文件视频切片上传的处理方法

时间:2023-11-24 10:32:27浏览次数:41  
标签:vue console log chunkInfo res 详解 file 上传

前端上传大文件、视频的时候会出现超时、过大、很慢等情况,为了解决这一问题,跟后端配合做了一个切片的功能,接下来就详细的给大家介绍一下vue大文件视频切片上传的处理方法,需要的朋友可以参考下

 

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

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

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

import axios from 'axios';
import md5 from 'js-md5' //引入MD5加密
export const uploadByPieces = ({ urlList, file, pieceSize, progress, success, error }) => {
    // 如果文件传入为空直接 return 返回
    if (!file) 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()
        // console.log('file', file)
        fileRederInstance.readAsBinaryString(file)
        fileRederInstance.addEventListener('load', e => {
        let fileBolb = e.target.result
        fileMD5 = md5(fileBolb)
        // console.log('fileMD5', fileMD5)
        // console.log("文件未被上传,将分片上传")
        readChunkMD5()
        })
    }
    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("切片地址123" + urlList)
            // console.log("总片数" + chunkCount)
            // console.log("分片后的数据---测试:" + i)
            // console.log(chunk)
            let fileUrl = urlList[i];
            // console.log(fileUrl,'地址');
            uploadChunk({ chunk, currentChunk: i, chunkCount, fileUrl })
        }
    }
    const uploadChunk = (chunkInfo) => {
        // 上传请求方式1 (根据自身情况自行选择)
        axios({
            method: 'put',
            url: chunkInfo.fileUrl,
        }).then((res) => {
            // console.log("分片上传返回信息:"+ res)
            // console.log(res.status)
            if (res.status == 200) {
                // success(res.data[0])
                // 下面如果在项目中没有用到可以不用打开注释
                if (chunkInfo.currentChunk < chunkInfo.chunkCount - 1) {
                    // console.log("分片上传成功")
                } else {
                    // 当总数大于等于分片个数的时候
                    if ((chunkInfo.currentChunk + 1) == chunkInfo.chunkCount) {
                        // console.log("文件开始------合并成功")
                        success(res.data[0])
                    }
                }
            }
        }).catch((e) => {
            console.log('失败!');
            error && error(e)
        });
        //  上传请求方式2 (根据自身情况自行选择)
        /*let config = {
            headers: {
                'Content-Type': 'multipart/form-data'
            }
        }
        console.log(chunkInfo,'chunkInfochunkInfo');
        创建formData对象,下面是结合不同项目给后端传入的对象。
        let fetchForm = new FormData()
        fetchForm.append('identifier', randoms)
        fetchForm.append('chunkNumber', chunkInfo.currentChunk + 1)
        fetchForm.append('chunkSize', chunkSize)
        fetchForm.append('currentChunkSize', chunkInfo.chunk.size)
        fetchForm.append('file', chunkInfo.chunk)
        fetchForm.append('filename', file.name)
        fetchForm.append('totalChunks', chunkInfo.chunkCount)
        fetchForm.append('totalSize', chunkSize)
        fetchForm.append('md5', fileMD5)
        api.queryUploadUploadAllFileLink(fetchForm, config).then(res => {
            console.log("分片上传返回信息:"+ res)
            if (res.code == 200) {
                // 结合不同项目 将成功的信息返回出去,这里可变的是指 res.data[0]
                success(res.data[0])
                // 下面如果在项目中没有用到可以不用打开注释
                // if (chunkInfo.currentChunk < chunkInfo.chunkCount - 1) {
                //   console.log("分片上传成功")
                // } else {
                //   // 当总数大于等于分片个数的时候
                //   if ((chunkInfo.currentChunk + 1) == chunkInfo.chunkCount) {
                //     console.log("文件开始------合并成功")
                //     success(res.data[0])
                //   }
                // }
            }
            else {
                console.log(res.message)
            }
        }).catch((e) => {
            error && error(e)
        })*/
    }
    readFileMD5() // 开始执行代码
}

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

npm install js-md5

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

<template>
	<div class="container" style="display:inline-block;width: 200px;">
		<el-upload
			class="upload-demo"
			action="#"
			:multiple="false"
			:auto-upload="false"
			accept=".mp4"
			:on-change="handleChange"
			:show-file-list="false">
			<el-button slot="trigger" size="small" type="primary">选择视频</el-button>
			<!-- <el-button size="small" type="primary" @click="uploadVideo()" style="margin-left: 10px;">开始上传</el-button> -->
		</el-upload>
		<!-- 进度条 -->
		<el-progress v-if="progressFlag" :percentage="loadProgress"></el-progress>
	</div>
</template>
<script>
import { uploadByPieces } from '@/util/upload'
import api from "@/api/mes2/index-lhj"
export default {
	data() {
		return {
			loadingFile1: false,
			uploadId: '', // 切片视频的唯一id(后端返回)
			fileNameVal: '', // 文件名称(后端返回)
			listUrl: [], // 切片路径集合
			loadProgress: 0, // 动态显示进度条
			progressFlag: false, // 关闭进度条
		}
	},
	created(){
	},
	props:{
		paramsData: {
			type: Object,
			default: {}
		}
	},
	methods: {
		// 选择视频
		handleChange(file, fileList) {
			this.progressFlag = true; // 显示进度条
			this.loadProgress = 25; // 动态获取文件上传进度
			let params = {
				fileName: file.name,
				partCount: 3,
				fileType: "mp4",
				fileSize: file.size,
				sourceId: this.paramsData.id,
				sourceType: this.paramsData.inspectionType,
				sourceSystem: "MES2",
				hierarchyCode:"MES2"
			}
			api.queryUploadBigFileUrl(params).then((res) => { // 调用后端接口,后端会返回所有切片的路径,及其他参数
				this.loadProgress = 50;
				this.listUrl = res.data.data.partUrlList;
				this.uploadId = res.data.data.uploadId;
				this.fileNameVal = res.data.data.fileName
				// 调用切片方法
				uploadByPieces({
					urlList: this.listUrl,
					file: file.raw, // 视频实体
					pieceSize: 5, // 分片大小
					success: data => {
						// console.log('分片上传视频成功', data)
						this.loadProgress = 75;
						this.getFileAll()
					},
					error: e => {
						console.log('分片上传视频失败', e)
						this.$message.error('视频切片上传失败,请重新上传!')
					}
				})
			}).catch(() => {
				this.$message.error('发生错误,请重新上传!')
				this.progressFlag = false
			})
		},
		// 整合切片文件(最后调用接口整合所有切片进行合并)
		getFileAll(){
			let params = {
				partCount: 3,
				tenantId: this.userInfo.tenant_id,
				uploadId: this.uploadId,
				fileName: this.fileNameVal,
			}
			this.loadProgress = 95;
			api.queryUploadBigFile(params).then(() => {
				this.loadProgress = 100;
				this.$message.success('视频上传成功!')
				if (this.loadProgress >= 100) {
					this.loadProgress = 100
					setTimeout( () => {this.progressFlag = false}, 1000) // 一秒后关闭进度条
				}
			}).catch(() => {
				this.$message.error('视频合并上传失败,请重新上传!')
			})
		},
	},
}
</script>
<style scoped lang="scss">
</style>

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

 

参考文章:http://blog.ncmem.com/wordpress/2023/10/21/详解vue大文件视频切片上传的处理方法/


标签:vue,console,log,chunkInfo,res,详解,file,上传
From: https://blog.51cto.com/u_14023400/8545024

相关文章

  • java实现大文件的分片上传与下载(springboot+vue3)
    1.1项目背景对于超大文件上传我们可能遇到以下问题•大文件直接上传,占用过多内存,可能导致内存溢出甚至系统崩溃•受网络环境影响,可能导致传输中断,只能重新传输•传输时间长,用户无法知道传输进度,用户体验不佳1.2项目目标对于上述问题,我们需要对文件做分片传输。分片传输就是......
  • HTTP请求响应码详解 1XX/2XX/3XX/4XX/5XX
      转载自:https://blog.csdn.net/qq_43565087/article/details/124696787......
  • 集合框架详解 [精选]
    Hii,mJinXiang⭐前言⭐本篇文章主要介绍集合框架的两个接口超级详细介绍,集合框架的使用以及部分理论知识......
  • uniapp+vue3中使用swiper和自定义header实现左右滑动的Tabs功能
    首先创建一个Tabs的Header,包含有一个下划线的指示器,在点击tabs的标题时候下划线会跟着动态的滑动下面是完整的Tabs的代码,可以看到定义了Tabs的background颜色样式,包含tab的宽度indicatorWidth,以及下划线的颜色indicatorColor主要的是tabList属性,通过tabList传入对应的tab数组得......
  • .Net Core MVC超大文件上传
    后端控制器://用于保存的文件夹staticreadonlystringuploadFolder="UploadFolder";//目录分隔符,兼容不同系统staticreadonlychardirSeparator=Path.DirectorySeparatorChar;stringGetTmpChunkDir(stringfileName)=>HttpContext.Session.TryGet......
  • 前端vue使用表单form或表格table时的注意事项
     如图,该table表格的data名字为:MyData因此在后面需要在表格里展示数据的时候需要给MyData赋值如下图  注意必须为 1result.data.data 不能是result.data......
  • 【最新最全指南】Vue项目安装eslint配置说明
    本指南都适配windows和mac下的开发项目第一步:安装1、全局安装:eslint(最好全局安装1个,配置出错debug方便)npminstalleslint-g2、项目本地dev安装:eslint(也可不安装,后面安装eslint-plugin-vue时候,默认会一起安装eslint)npminstalleslint-D3、项目本地dev安装插件:eslint-plu......
  • Springboot文件上传代码笔记
    1.在src下创建filter包,包内Class名UploadFilterpackagecom.gd.filter;importorg.apache.catalina.servlet4preview.http.HttpServletRequest;importjavax.servlet.*;importjavax.servlet.annotation.WebFilter;importjavax.servlet.http.HttpServletResponse;impor......
  • 在vue2.0 项目中集成 Electron 实现桌面端应用
    需求:在桌面端有个应用能直接打开项目,不用在浏览器中浏览。方案:vue2.0+Electron关于vue的项目搭建和electron的相关介绍可以去官网了解,这里是直接在已经开发好的vue2.0的项目中直接加入electron。electron介绍:参考1: https://electronjs.p2hp.com/参考2:https://www.......
  • 全屏API及vue3 hook封装
    最近在一个大屏项目遇到一个需求:用户可以通过一个按钮,触发页面部分模块全屏。通过以下API可以实现:Element.requestFullscreen()方法用于发出异步请求使元素进入全屏模式。且全屏状态变化会触发以下事件:fullscreenchange事件会在浏览器进入或退出全屏模式后立即触发。基于......