前端上传大文件、视频的时候会出现超时、过大、很慢等情况,为了解决这一问题,跟后端配合做了一个切片的功能。
我这个切片功能是基于 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, beforeSuccess, success, error }) => {
// 如果文件传入为空直接 return 返回
if (!file) return
let fileMD5 = ''// 总文件列表
const chunkSize = pieceSize * 1024 * 1024 // 5MB一片
const chunkCount = Math.ceil(file.size / chunkSize - 1) // 总片数
// 获取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 (根据自身情况自行选择)
// console.log(chunkInfo.chunk,'chunkInfochunkInfo');
let files = chunkInfo.chunk
axios.put(chunkInfo.fileUrl,files).then((res) => {
// console.log("分片上传返回信息:"+ res)
if (res.status == 200) {
// 下面如果在项目中没有用到可以不用打开注释
if (chunkInfo.currentChunk < chunkInfo.chunkCount - 1) {
beforeSuccess()
} else {
// 当总数大于等于分片个数的时候
if ((chunkInfo.currentChunk + 1) == chunkInfo.chunkCount) {
// console.log("文件开始------合并成功")
success(res.data[0])
}
}
}
}).catch((e) => {
console.log('失败!');
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" :disabled="isUploadVideo">选择视频</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 {mapGetters} from "vuex";
import { uploadByPieces } from '@/util/upload-video'
import api from "@/api/mes2/index-lhj"
export default {
data() {
return {
isUploadVideo: false,
uploadId: '', // 切片视频的唯一id(后端返回)
fileNameVal: '', // 文件名称(后端返回)
listUrl: [], // 切片路径集合
loadProgress: 0, // 动态显示进度条
progressFlag: false, // 关闭进度条
}
},
created(){
},
computed: {
...mapGetters(["userInfo"]),
},
props:{
paramsData: {
type: Object,
default: {}
}
},
methods: {
// 选择视频
handleChange(file, fileList) {
this.isUploadVideo = true;
this.progressFlag = true; // 显示进度条
this.loadProgress = 10; // 动态获取文件上传进度
let fileSizeVal = file.size / 1024 / 1024;
let numVal = null;
if(fileSizeVal <= 20){
numVal = 1;
}else{
numVal = Math.ceil(file.size / (10 * 1024 * 1024));
}
let params = {
fileName: file.name,
partCount: numVal - 1,
tenantId: this.userInfo.tenant_id,
fileType: "mp4",
fileSize: file.size,
sourceId: this.paramsData.id,
sourceType: this.paramsData.inspectionType,
sourceSystem: "MES2",
hierarchyCode:"MES2"
}
api.queryUploadBigFileUrl(params).then((res) => {
this.loadProgress = 20;
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: 10, // 分片大小
beforeSuccess: data => {
// 进度数 / 切片总数
let progress = Math.floor(70 / (numVal - 1)); // 计算进度
this.loadProgress += progress;
},
success: data => {
// console.log('分片上传视频成功', data)
this.getFileAll(numVal)
},
error: e => {
console.log('分片上传视频失败', e)
this.$message.error('视频切片上传失败,请重新上传!')
this.progressFlag = false
}
})
}).catch(() => {
this.$message.error('发生错误,请重新上传!')
this.progressFlag = false
})
},
// 整合切片文件
getFileAll(numVal){
let params = {
partCount: numVal - 1,
tenantId: this.userInfo.tenant_id,
uploadId: this.uploadId,
fileName: this.fileNameVal,
}
this.loadProgress = 95;
api.queryUploadBigFile(params).then((res) => {
if(res.data.data === false){
this.isUploadVideo = false;
this.$message.error('视频切片合并失败,请重新上传!')
setTimeout( () => {this.progressFlag = false}, 1000) // 一秒后关闭进度条
}else{
this.loadProgress = 100;
this.isUploadVideo = false;
this.$message.success('视频上传成功!')
this.$emit('uploadVideoData');
if (this.loadProgress >= 100) {
this.loadProgress = 100
setTimeout( () => {this.progressFlag = false}, 1000) // 一秒后关闭进度条
}
}
}).catch(() => {
this.isUploadVideo = false;
this.$message.error('视频合并上传失败,请重新上传!')
})
},
},
}
</script>
<style scoped lang="scss">
</style>
具体根据自己的实际情况进行修改即可!
至此完成!!!文章来源:https://www.toymoban.com/news/detail-647401.html
测试有效!!!感谢支持!!!文章来源地址https://www.toymoban.com/news/detail-647401.html
到了这里,关于vue 大文件视频切片上传处理方法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!