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

前端上传大文件、视频的时候会出现超时、过大、很慢等情况,为了解决这一问题,跟后端配合做了一个切片的功能,接下来就详细的给大家介绍一下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/%e8%af%a6%e8%a7%a3vue%e5%a4%a7%e6%96%87%e4%bb%b6%e8%a7%86%e9%a2%91%e5%88%87%e7%89%87%e4%b8%8a%e4%bc%a0%e7%9a%84%e5%a4%84%e7%90%86%e6%96%b9%e6%b3%95/
欢迎入群一起讨论

在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue.js是一个流行的JavaScript框架,用于构建界面。如果你需要在Vue.js中实现大文件切片上传,可以按照以下步骤进行操作: 1.装依赖:首先,你需要安装一些必要的依赖库。可以使用npm或yarn来安装这些库。例如,你可以使用以下命令来安装axios和element-ui: ``` npm install axios element-ui ``` 2. 创建上传组件:创建一个Vue组件,用于处理文件上传。在这个组件中,你可以使用element-ui来创建上传按钮和进度条,并使用axios库来发送文件切片。 3. 切片文件:在前端,你可以使用File API将大文件切成小块。使用FileReader读取文件内容,然后将其分割成多个切片。你可以指定切片的大小,通常是几百KB或几MB。 4. 上传切片:将切片上传到服务器。你可以使用axios发送HTTP请求将切片发送到服务器的特定接口。在请求中,你可以包含切片的索引、总切片数以及文件标识符等信息。 5. 合并切片:在服务器端,接收到切片后,你需要将它们按顺序合并成完整的文件。可以使用Node.js或其他后端语言来实现此逻辑。一种常见的方法是在服务器端创建一个临时文件夹,在接收到所有切片后,将它们合并成一个完整的文件,并将其保存到目标位置。 6. 进度显示:在前端,你可以使用element-ui的进度条组件来显示上传进度。可以根据已上传切片数和总切片数来计算上传进度,并将其传递给进度条组件进行显示。 需要注意的是,大文件切片上传涉及到前后端的协作,你需要在服务器端实现对应的接口来接收和处理切片,并进行合并操作。 以上是一个大致的实现思路,具体的代码实现可能会有所不同,取决于你使用的具体库和后端语言。你可以根据这个思路进行进一步的开发和调试。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值