赞
踩
前端上传大文件、视频的时候会出现超时、过大、很慢等情况,为了解决这一问题,跟后端配合做了一个切片的功能。
我这个切片功能是基于 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>

具体根据自己的实际情况进行修改即可!
至此完成!!!
测试有效!!!感谢支持!!!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。