JavaScript實(shí)現(xiàn)大文件上傳的示例代碼
下面就是JavaScript實(shí)現(xiàn)大文件上傳功能的代碼
bigFileUpload.js
const path = require('path')
import axios from 'axios'
import { resolve } from 'path';
import { promised } from 'q';
// 遞歸調(diào)用請(qǐng)求
async function dg(requestMargreList, options, key = 0) {
let index = key
const requestList = requestMargreList[key].map(({ formData }) =>
{
return multipartUploadUpload(formData, options)
}
);
const resArr = await Promise.all(requestList);
let boolean = resArr.every(item => item?.data?.status == 'SUCCEED')
if(boolean){
index++
if(index == requestMargreList.length) {
return {uploadFlag: true, msg: '上傳切片文件成功' }
}
return dg(requestMargreList, options, index)
} else {
const res_err = resArr.map(item => item?.data?.status != 'SUCCEED')
return {uploadFlag: false, msg: '切片文件上傳出錯(cuò),請(qǐng)重新嘗試' }
}
}
// 文件切片
function createFileChunk(file, size){
let fileChunkList = [];
let cur = 0;
while (cur < file.size) {
fileChunkList.push({file:file.slice(cur, cur + size)})
cur += size;
}
return fileChunkList
}
function calculateHash(fileChunkList, container,options ={}) {
return new Promise(resolve => {
// 添加 worker 屬性
container.worker = new Worker("/static/hash.js");
container.worker.postMessage({ fileChunkList });
container.worker.onmessage = e => {
const { percentage, hash } = e.data;
// 總進(jìn)度變化
// hashPercentage = percentage;
options.showHash(percentage)
if (hash) {
resolve(hash);
}
};
})
}
function getMultipartLogId(params){
return new Promise(resolve =>{
axios.post('api/multipartUploadInit',params)
.then(res=>{
resolve(res)
})
})
}
let globalPercentage = 0;
function multipartUploadUpload(formData, options) {
return axios.post('api/multipartUploadUpload',formData,{
onUploadProgress: function (upEvent) { // 文件上傳總進(jìn)度
let percentage = ((options.size * (formData.get('chunkIndex')- 1) + upEvent.loaded) / options.fileSize)*100
//options.size為分片后每片的大小 options.fileSize為文件總大小 percentage為計(jì)算后總進(jìn)度
if(percentage > globalPercentage){
globalPercentage = percentage;
}
if(globalPercentage>100) globalPercentage = 100;
options.showFileProgress(globalPercentage)
}
})
}
async function uploadChunks(fileChunkList, options) {
let reqMargeArr = [], reqSize = 3, uploadResObj = {};
let reqBeforeList = fileChunkList.map(({ multipartLogId,hash,file,fileName,chunkIndex }) => {
const formData = new FormData();
formData.append("multipartLogId", multipartLogId);
formData.append("hash", hash);
formData.append("file", file);
formData.append("fileName", fileName);
formData.append("chunkIndex", chunkIndex);
return { formData };
})
if(reqBeforeList.length > reqSize) {
for (let i = 0; i < reqBeforeList.length; i += reqSize) {
reqMargeArr.push(reqBeforeList.slice(i, i + reqSize))
}
const {uploadFlag, msg} = await dg(reqMargeArr, options,)
uploadResObj = { uploadFlag, msg}
} else {
const requestList = reqBeforeList.map(({ formData }) =>
{
return multipartUploadUpload(formData, options)
});
let resArr = await Promise.all(requestList);
const uploadFlag = resArr.every(item => item?.data?.status == 'SUCCEED')
uploadResObj = { uploadFlag, msg: uploadResObj.uploadFlag?'上傳切片文件成功':'切片文件上傳出錯(cuò),請(qǐng)重新嘗試'}
}
if(uploadResObj.uploadFlag) {
// completeFunc函數(shù)中有回調(diào)接口判斷是否合并成功
setTimeout(()=>{
completeFunc(fileChunkList[0].multipartLogId,options)
}, 1000)
} else {
return uploadResObj
}
}
function completeFunc(multipartLogId, options) {
return axios.post('api/multipartUploadComplete',{multipartLogId})
.then(res=>{
options.completeFunc(res)
})
}
async function bigFileUpload(file, options={},fileOptions) {
let container = {}
let fileChunkList = createFileChunk(file,options?.size);
const fileHash = await calculateHash(fileChunkList, container,options);
fileOptions.hash = fileHash
const upFileParams = await getMultipartLogId(fileOptions)
// 刪除已上傳的文件片
let fileChunkListArr = [];
let percentage = 0;
if(upFileParams.data.status == 'SUCCEED'){
let chunkIndexs = upFileParams?.data?.data?.chunkIndexs;
if(chunkIndexs?.length>0){
fileChunkList.map(({ file },index) => {
if(!chunkIndexs.includes(index+1)){
fileChunkListArr.push({
multipartLogId: upFileParams.data.data.multipartLogId,
chunkIndex: index + 1,
hash: fileHash,
file: file,
fileName: fileOptions.fileName,
})
}
});
percentage = percentage + (chunkIndexs.length * fileOptions.chunkSize / options.fileSize)*100
options.showFileProgress(percentage)
} else {
fileChunkList.map(({ file },index) => {
fileChunkListArr.push({
multipartLogId: upFileParams.data.data.multipartLogId,
chunkIndex: index + 1,
hash: fileHash,
file: file,
fileName: fileOptions.fileName,
})
}
);
}
if(fileChunkListArr.length>0){
// 上傳文件切片
const uploadRes = await uploadChunks(fileChunkListArr, options,percentage)
return uploadRes
} else {
completeFunc(upFileParams.data.data.multipartLogId,options)
}
} else {
return { uplodFlag: false, msg: upFileParams.data.extMessage }
}
}
export default bigFileUpload
import bigFileUpload from './components/bigFileUpload'
// 大文件上傳
// 分片大小 bigFileUpload
let fileParams = {
size: bigSize, // 切片大小
fileSize: fileTem.size,
showHash: this.showHash,
showFileProgress: this.showFileProgress,
completeFunc: this.completeFunc,
}
this.fileOptions = fileOptions
const res = await bigFileUpload(fileTem, fileParams,fileOptions)
console.log("=====big up res========", res)
if(res && !res.uplodFlag) {
_this.$Notice.error({
title: '提醒',
desc: res.msg
})
return
}到此這篇關(guān)于JavaScript實(shí)現(xiàn)大文件上傳的示例代碼的文章就介紹到這了,更多相關(guān)JavaScript大文件上傳內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JavaScript中eval函數(shù)的問(wèn)題
這篇文章主要介紹了JavaScript中eval函數(shù)的問(wèn)題,需要的朋友可以參考下2016-01-01
JavaScript+CSS相冊(cè)特效實(shí)例代碼
下面小編就為大家?guī)?lái)一篇JavaScript+CSS相冊(cè)特效實(shí)例代碼。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-09-09
處理Axios返回Promise對(duì)象的幾種常見(jiàn)方式
Axios返回的是Promise對(duì)象,這意味著可以使用Promise的.then()、.catch()和.finally()方法來(lái)處理異步操作的結(jié)果,本文詳細(xì)介紹了處理Axios返回Promise對(duì)象的幾種常見(jiàn)方式,需要的朋友可以參考下2024-09-09
用函數(shù)模板,寫(xiě)一個(gè)簡(jiǎn)單高效的 JSON 查詢器的方法介紹
本篇文章小編將為大家介紹,用函數(shù)模板,寫(xiě)一個(gè)簡(jiǎn)單高效的 JSON 查詢器的方法介紹,需要的朋友可以參考一下2013-04-04
一文帶你理解微信小程序中RPC通信的實(shí)現(xiàn)
在微信小程序開(kāi)發(fā)中,要實(shí)現(xiàn)兩個(gè)線程之間的通信是一項(xiàng)重要的任務(wù),所以本文就來(lái)講講如何使用小程序的?postMessage?和?addListener?API?來(lái)實(shí)現(xiàn)在兩個(gè)線程之間進(jìn)行高效的?RPC?通信吧2023-06-06
javascript 構(gòu)建模塊化開(kāi)發(fā)過(guò)程解析
這篇文章主要介紹了javascript 構(gòu)建模塊化開(kāi)發(fā)過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-09-09
JavaScript控制listbox列表框的項(xiàng)目上下移動(dòng)的方法
這篇文章主要介紹了JavaScript控制listbox列表框的項(xiàng)目上下移動(dòng)的方法,實(shí)例分析了javascript操作listbox列表框的技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2015-03-03
微信小程序?qū)崿F(xiàn)兩邊小中間大的輪播效果的示例代碼
這篇文章主要介紹了微信小程序?qū)崿F(xiàn)兩邊小中間大的輪播效果的示例代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-12-12

