詳解vue大文件視頻切片上傳的處理方法
前端上傳大文件、視頻的時(shí)候會(huì)出現(xiàn)超時(shí)、過大、很慢等情況,為了解決這一問題,跟后端配合做了一個(gè)切片的功能。
我這個(gè)切片功能是基于 minion 的,后端會(huì)把文件放在minion服務(wù)器上。具體看后端怎么做
1、在項(xiàng)目的 util(這個(gè)文件夾是自己創(chuàng)建的,如果項(xiàng)目里沒有可以自行創(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)目中沒有用到可以不用打開注釋
if (chunkInfo.currentChunk < chunkInfo.chunkCount - 1) {
// console.log("分片上傳成功")
} else {
// 當(dāng)總數(shù)大于等于分片個(gè)數(shù)的時(shí)候
if ((chunkInfo.currentChunk + 1) == chunkInfo.chunkCount) {
// console.log("文件開始------合并成功")
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)目中沒有用到可以不用打開注釋
// if (chunkInfo.currentChunk < chunkInfo.chunkCount - 1) {
// console.log("分片上傳成功")
// } else {
// // 當(dāng)總數(shù)大于等于分片個(gè)數(shù)的時(shí)候
// if ((chunkInfo.currentChunk + 1) == chunkInfo.chunkCount) {
// console.log("文件開始------合并成功")
// success(res.data[0])
// }
// }
}
else {
console.log(res.message)
}
}).catch((e) => {
error && error(e)
})*/
}
readFileMD5() // 開始執(zhí)行代碼
}js-md5 如果沒有的話需要自己在項(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;">開始上傳</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)文章
vue移動(dòng)端項(xiàng)目中如何實(shí)現(xiàn)頁面緩存的示例代碼
這篇文章主要介紹了vue移動(dòng)端項(xiàng)目中如何實(shí)現(xiàn)頁面緩存的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03
Vue讀取本地靜態(tài).md并側(cè)邊欄導(dǎo)航跳轉(zhuǎn)、展示.md文件的操作方法
這篇文章主要介紹了Vue讀取本地靜態(tài).md并側(cè)邊欄導(dǎo)航跳轉(zhuǎn)、展示.md文件,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-08-08
vue.js 2.0實(shí)現(xiàn)簡(jiǎn)單分頁效果
這篇文章主要為大家詳細(xì)介紹了vue.js 2.0實(shí)現(xiàn)簡(jiǎn)單分頁效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-07-07
Vue將props值實(shí)時(shí)傳遞 并可修改的操作
這篇文章主要介紹了Vue將props值實(shí)時(shí)傳遞 并可修改的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-08-08
vue2基本響應(yīng)式實(shí)現(xiàn)方式之讓數(shù)組也變成響應(yīng)式
這篇文章主要介紹了vue2基本響應(yīng)式實(shí)現(xiàn)方式之讓數(shù)組也變成響應(yīng)式問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-04-04
vue3中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

