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)用請求 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ò),請重新嘗試' } } } // 文件切片 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ò),請重新嘗試'} } 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)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
用函數(shù)模板,寫一個(gè)簡單高效的 JSON 查詢器的方法介紹
本篇文章小編將為大家介紹,用函數(shù)模板,寫一個(gè)簡單高效的 JSON 查詢器的方法介紹,需要的朋友可以參考一下2013-04-04一文帶你理解微信小程序中RPC通信的實(shí)現(xiàn)
在微信小程序開發(fā)中,要實(shí)現(xiàn)兩個(gè)線程之間的通信是一項(xiàng)重要的任務(wù),所以本文就來講講如何使用小程序的?postMessage?和?addListener?API?來實(shí)現(xiàn)在兩個(gè)線程之間進(jìn)行高效的?RPC?通信吧2023-06-06javascript 構(gòu)建模塊化開發(fā)過程解析
這篇文章主要介紹了javascript 構(gòu)建模塊化開發(fā)過程解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-09-09JavaScript控制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)兩邊小中間大的輪播效果的示例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-12-12