詳解vue大文件視頻切片上傳的處理方法
前端上傳大文件、視頻的時(shí)候會(huì)出現(xiàn)超時(shí)、過(guò)大、很慢等情況,為了解決這一問(wèn)題,跟后端配合做了一個(gè)切片的功能。
我這個(gè)切片功能是基于 minion 的,后端會(huì)把文件放在minion服務(wù)器上。具體看后端怎么做
1、在項(xiàng)目的 util(這個(gè)文件夾是自己創(chuàng)建的,如果項(xiàng)目里沒(méi)有可以自行創(chuàng)建) 文件家中創(chuàng)建一個(gè)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) // 總片數(shù) // 獲取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 } } // 針對(duì)每個(gè)文件進(jìn)行chunk處理 const readChunkMD5 = () => { // 針對(duì)單個(gè)文件進(jìn)行chunk上傳 for (var i = 0; i < chunkCount; i++) { const { chunk } = getChunkInfo(file, i, chunkSize) // console.log("切片地址123" + urlList) // console.log("總片數(shù)" + chunkCount) // console.log("分片后的數(shù)據(jù)---測(cè)試:" + i) // console.log(chunk) let fileUrl = urlList[i]; // console.log(fileUrl,'地址'); uploadChunk({ chunk, currentChunk: i, chunkCount, fileUrl }) } } const uploadChunk = (chunkInfo) => { // 上傳請(qǐng)求方式1 (根據(jù)自身情況自行選擇) axios({ method: 'put', url: chunkInfo.fileUrl, }).then((res) => { // console.log("分片上傳返回信息:"+ res) // console.log(res.status) if (res.status == 200) { // success(res.data[0]) // 下面如果在項(xiàng)目中沒(méi)有用到可以不用打開(kāi)注釋 if (chunkInfo.currentChunk < chunkInfo.chunkCount - 1) { // console.log("分片上傳成功") } else { // 當(dāng)總數(shù)大于等于分片個(gè)數(shù)的時(shí)候 if ((chunkInfo.currentChunk + 1) == chunkInfo.chunkCount) { // console.log("文件開(kāi)始------合并成功") success(res.data[0]) } } } }).catch((e) => { console.log('失?。?); error && error(e) }); // 上傳請(qǐng)求方式2 (根據(jù)自身情況自行選擇) /*let config = { headers: { 'Content-Type': 'multipart/form-data' } } console.log(chunkInfo,'chunkInfochunkInfo'); 創(chuàng)建formData對(duì)象,下面是結(jié)合不同項(xiàng)目給后端傳入的對(duì)象。 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) { // 結(jié)合不同項(xiàng)目 將成功的信息返回出去,這里可變的是指 res.data[0] success(res.data[0]) // 下面如果在項(xiàng)目中沒(méi)有用到可以不用打開(kāi)注釋 // if (chunkInfo.currentChunk < chunkInfo.chunkCount - 1) { // console.log("分片上傳成功") // } else { // // 當(dāng)總數(shù)大于等于分片個(gè)數(shù)的時(shí)候 // if ((chunkInfo.currentChunk + 1) == chunkInfo.chunkCount) { // console.log("文件開(kāi)始------合并成功") // success(res.data[0]) // } // } } else { console.log(res.message) } }).catch((e) => { error && error(e) })*/ } readFileMD5() // 開(kāi)始執(zhí)行代碼 }
js-md5 如果沒(méi)有的話需要自己在項(xiàng)目里安裝:
npm install js-md5
2、創(chuàng)建一個(gè)上傳視頻文件的公共組件,便于不同地方引用,如下:
<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;">開(kāi)始上傳</el-button> --> </el-upload> <!-- 進(jìn)度條 --> <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, // 動(dòng)態(tài)顯示進(jìn)度條 progressFlag: false, // 關(guān)閉進(jìn)度條 } }, created(){ }, props:{ paramsData: { type: Object, default: {} } }, methods: { // 選擇視頻 handleChange(file, fileList) { this.progressFlag = true; // 顯示進(jìn)度條 this.loadProgress = 25; // 動(dòng)態(tài)獲取文件上傳進(jìn)度 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) => { // 調(diào)用后端接口,后端會(huì)返回所有切片的路徑,及其他參數(shù) this.loadProgress = 50; this.listUrl = res.data.data.partUrlList; this.uploadId = res.data.data.uploadId; this.fileNameVal = res.data.data.fileName // 調(diào)用切片方法 uploadByPieces({ urlList: this.listUrl, file: file.raw, // 視頻實(shí)體 pieceSize: 5, // 分片大小 success: data => { // console.log('分片上傳視頻成功', data) this.loadProgress = 75; this.getFileAll() }, error: e => { console.log('分片上傳視頻失敗', e) this.$message.error('視頻切片上傳失敗,請(qǐng)重新上傳!') } }) }).catch(() => { this.$message.error('發(fā)生錯(cuò)誤,請(qǐng)重新上傳!') this.progressFlag = false }) }, // 整合切片文件(最后調(diào)用接口整合所有切片進(jìn)行合并) 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) // 一秒后關(guān)閉進(jìn)度條 } }).catch(() => { this.$message.error('視頻合并上傳失敗,請(qǐng)重新上傳!') }) }, }, } </script> <style scoped lang="scss"> </style>
具體根據(jù)自己的實(shí)際情況進(jìn)行修改即可!
到此這篇關(guān)于詳解vue大文件視頻切片上傳的處理方法的文章就介紹到這了,更多相關(guān)vue大文件視頻切片上傳內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue3中addRoute路由變化頁(yè)面未刷新問(wèn)題解決
這篇文章主要為大家介紹了vue3中addRoute路由變化但頁(yè)面未刷新問(wèn)題解決,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06vue移動(dòng)端項(xiàng)目中如何實(shí)現(xiàn)頁(yè)面緩存的示例代碼
這篇文章主要介紹了vue移動(dòng)端項(xiàng)目中如何實(shí)現(xiàn)頁(yè)面緩存的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03Vue讀取本地靜態(tài).md并側(cè)邊欄導(dǎo)航跳轉(zhuǎn)、展示.md文件的操作方法
這篇文章主要介紹了Vue讀取本地靜態(tài).md并側(cè)邊欄導(dǎo)航跳轉(zhuǎn)、展示.md文件,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-08-08vue.js 2.0實(shí)現(xiàn)簡(jiǎn)單分頁(yè)效果
這篇文章主要為大家詳細(xì)介紹了vue.js 2.0實(shí)現(xiàn)簡(jiǎn)單分頁(yè)效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-07-07vue 支持百萬(wàn)量級(jí)的無(wú)限滾動(dòng)組件詳解
這篇文章主要為大家介紹了vue 支持百萬(wàn)量級(jí)的無(wú)限滾動(dòng)組件詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-02-02Vue將props值實(shí)時(shí)傳遞 并可修改的操作
這篇文章主要介紹了Vue將props值實(shí)時(shí)傳遞 并可修改的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-08-08vue2基本響應(yīng)式實(shí)現(xiàn)方式之讓數(shù)組也變成響應(yīng)式
這篇文章主要介紹了vue2基本響應(yīng)式實(shí)現(xiàn)方式之讓數(shù)組也變成響應(yīng)式問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-04-04vue3中element-plus?icon圖標(biāo)的正確使用姿勢(shì)
element-plus官方提示,Icon圖標(biāo)正在向SVG?Icon遷移,之前使用的Font?Icon即將被棄用,下面這篇文章主要給大家介紹了關(guān)于vue3中element-plus?icon圖標(biāo)的正確使用姿勢(shì),需要的朋友可以參考下2022-03-03