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

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

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

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

javascript 复制代码
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 如果没有的话需要自己在项目里安装:

javascript 复制代码
npm install js-md5

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

html 复制代码
<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>

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

至此完成!!!

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

相关推荐
崔庆才丨静觅6 分钟前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60611 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了1 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅1 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅1 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅2 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment2 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅2 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊2 小时前
jwt介绍
前端
爱敲代码的小鱼2 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax