1、選擇本地視頻,獲取視頻實體
第一步::auto-upload="false";:on-change="videoSaveToUrl"
<el-upload
action
:auto-upload="false"
:on-change="videoSaveToUrl"
:accept="'video/*'">
</el-upload>
第二步:在videoSaveToUrl方法中獲取視頻實體,並存放在data數據的this.video中
videoSaveToUrl(event) {
this.video = event.raw;
}
2、單擊“上傳”按鈕,觸發分片上傳方法
//引入uploadByPieces方法
import { uploadByPieces } from "@/utils";
processButtonClick() {
uploadByPieces({
file: this.video,//視頻實體
pieceSize: 5, //分片大小
success: data => {
console.log("分片上傳視頻成功");
},
error: e => {
console.log("分片上傳視頻失敗");
}
});
}
3、分片上傳方法(utils.js代碼中的uploadByPieces方法)
第一步:獲取分片上傳過程中會使用到的變量
// 上傳過程中用到的變量
let fileMD5 = ''// 總文件列表
const chunkSize = pieceSize * 1024 * 1024 // 5MB一片
const chunkCount = Math.ceil(file.size / chunkSize) // 總片數
readFileMD5() // 開始執行代碼
第二步:readFileMD5方法:首先獲取文件的MD5值,並通過網絡請求uploadCheckAxios來檢查是否之前已上傳過該視頻(每個文件的MD5值是唯一的),如果已經上傳過,則后台直接返回視頻在服務器上的URL,如果沒有上傳則進行分片上傳,調用readChunkMD5() 方法
const readFileMD5 = () => {
// 讀取視頻文件的md5
console.log("獲取文件的MD5值")
let fileRederInstance = new FileReader()
fileRederInstance.readAsBinaryString(file)
fileRederInstance.addEventListener('load', e => {
let fileBolb = e.target.result
fileMD5 = md5(fileBolb)
uploadCheckAxios({
"md5": fileMD5
}).then(res => {
if (res.data.code == 0) {
console.log("文件已被上傳")
console.log(res.data)
success && success(res)
} else {
console.log("文件未被上傳,將分片上傳")
readChunkMD5()
}
}).catch((e) => {
console.log("文件合並錯誤")
console.log(e)
})
})
}
第三步:readChunkMD5() 方法:分片並上傳,其中uploadChunk為上傳方法
// 針對每個文件進行chunk處理
const readChunkMD5 = () => {
// 針對單個文件進行chunk上傳
for (var i = 0; i < chunkCount; i++) {
const { chunk } = getChunkInfo(file, i, chunkSize)
console.log("總片數"+chunkCount)
console.log("分片后的數據---測試:"+i)
console.log(chunk)
uploadChunk({ chunk, currentChunk: i, chunkCount })
}
}
// getChunkInfo方法獲取每片視頻
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 }
}
第四步:uploadChunk方法:首先分片上傳,上傳完畢后調用后台合並接口
const uploadChunk = (chunkInfo) => {
let fetchForm = new FormData()
fetchForm.append('chunk', chunkInfo.currentChunk)
fetchForm.append('chunkSize', chunkSize)
fetchForm.append('chunks', chunkInfo.chunkCount)
fetchForm.append('file', chunkInfo.chunk)
fetchForm.append('md5', fileMD5)
fetchForm.append('name', file.name)
uploadVideoChunkAxios(fetchForm).then(res => {
console.log("分片上傳返回信息:")
console.log(res.data)
if (res.data.code == 0) {
if (chunkInfo.currentChunk < chunkInfo.chunkCount - 1) {
console.log("文件分片上傳成功")
} else {
// 當總數大於等於分片個數的時候
if (chunkInfo.currentChunk >= chunkInfo.chunkCount - 1) {
console.log("文件開始------合並成功")
//調用合並接口,傳參為視頻文件的額MD5值以及名字
mergeFileAxios({
"md5": fileMD5,
"name": file.name
}).then(res => {
if (res.data.code == 0) {
success && success(res)
console.log("文件合並成功")
console.log(res.data.data.url)
} else {
console.log(res.data.msg)
}
}).catch((e) => {
console.log("文件合並錯誤")
console.log(e)
})
}
}
} else {
console.log(res.data.msg)
}
}).catch((e) => {
error && error(e)
})
}
4、utils.js的完整代碼
import md5 from 'js-md5'
import {
uploadVideoChunkAxios,
mergeFileAxios,
uploadCheckAxios
} from '@/api/upload'
export const uploadByPieces = ({
file,
pieceSize = 2,
progress,
success,
error
}) => {
// if (!file || !file.length) 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()
fileRederInstance.readAsBinaryString(file)
fileRederInstance.addEventListener('load', e => {
let fileBolb = e.target.result
fileMD5 = md5(fileBolb)
uploadCheckAxios({
"md5": fileMD5
}).then(res => {
if (res.data.code == 0) {
console.log("文件已被上傳")
console.log(res.data)
success && success(res)
} else {
console.log("文件未被上傳,將分片上傳")
readChunkMD5()
}
}).catch((e) => {
console.log("文件合並錯誤")
console.log(e)
})
})
}
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("總片數" + chunkCount)
console.log("分片后的數據---測試:" + i)
console.log(chunk)
uploadChunk({
chunk,
currentChunk: i,
chunkCount
})
}
}
const uploadChunk = (chunkInfo) => {
// progressFun()
let fetchForm = new FormData()
fetchForm.append('chunk', chunkInfo.currentChunk)
fetchForm.append('chunkSize', chunkSize)
fetchForm.append('chunks', chunkInfo.chunkCount)
fetchForm.append('file', chunkInfo.chunk)
fetchForm.append('md5', fileMD5)
fetchForm.append('name', file.name)
uploadVideoChunkAxios(fetchForm).then(res => {
console.log("分片上傳返回信息:")
console.log(res.data)
if (res.data.code == 0) {
// success && success(res)
if (chunkInfo.currentChunk < chunkInfo.chunkCount - 1) {
console.log("分片上傳成功")
} else {
// 當總數大於等於分片個數的時候
if (chunkInfo.currentChunk >= chunkInfo.chunkCount - 1) {
console.log("文件開始------合並成功")
mergeFileAxios({
"md5": fileMD5,
"name": file.name
}).then(res => {
if (res.data.code == 0) {
success && success(res)
console.log("文件合並成功")
console.log(res.data.data.url)
} else {
console.log(res.data.msg)
}
}).catch((e) => {
console.log("文件合並錯誤")
console.log(e)
})
}
}
} else {
console.log(res.data.msg)
}
}).catch((e) => {
error && error(e)
})
}
readFileMD5() // 開始執行代碼
}
說明
uploadVideoChunkAxios 是上傳分片視頻的接口
mergeFileAxios 是合並的接口
uploadCheckAxios 來檢查是否之前已上傳過該視頻