JavaScript实现大文件上传的示例代码
作者:freeman_Tian
这篇文章主要为大家详细介绍了JavaScript实现大文件上传功能的示例代码,文中的代码讲解详细,对我们学习JavaScript有一定帮助,感兴趣可以跟随小编一起学习一下
下面就是JavaScript实现大文件上传功能的代码
bigFileUpload.js
const path = require('path') import axios from 'axios' import { resolve } from 'path'; import { promised } from 'q'; // 递归调用请求 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: '切片文件上传出错,请重新尝试' } } } // 文件切片 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; // 总进度变化 // 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) { // 文件上传总进度 let percentage = ((options.size * (formData.get('chunkIndex')- 1) + upEvent.loaded) / options.fileSize)*100 //options.size为分片后每片的大小 options.fileSize为文件总大小 percentage为计算后总进度 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?'上传切片文件成功':'切片文件上传出错,请重新尝试'} } if(uploadResObj.uploadFlag) { // completeFunc函数中有回调接口判断是否合并成功 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 }
到此这篇关于JavaScript实现大文件上传的示例代码的文章就介绍到这了,更多相关JavaScript大文件上传内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!