JavaScript实现大文件上传的示例代码

 更新时间:2022年11月18日 09:17:06   作者: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大文件上传内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • JS中使用 after 伪类清除浮动实例

    JS中使用 after 伪类清除浮动实例

    这篇文章主要介绍了使用 after 伪类清除浮动实例,非常不错,具有参考借鉴价值,需要的的朋友参考下
    2017-03-03
  • javascript-简单的计算器实现步骤分解(附图)

    javascript-简单的计算器实现步骤分解(附图)

    输入内容的判断,对于事件对象的来源的判断以及数学运算“+,-,*,/”的使用,感兴趣的朋友可以学习下
    2013-05-05
  • JAVA四种基本排序方法实例总结

    JAVA四种基本排序方法实例总结

    这篇文章主要介绍了JAVA四种基本排序方法,较为详细的总结分析了插入法、冒泡法、选择法及Shell排序等四种常用的排序技巧,非常具有实用价值,需要的朋友可以参考下
    2015-07-07
  • JavaScript栏目列表隐藏/显示简单实现

    JavaScript栏目列表隐藏/显示简单实现

    隐藏侧边栏,并将图片换成右箭头图片;显示侧边栏,并将图片换成左箭头,这样的效果想必大家都很熟悉吧,接下来实现下,感兴趣的朋友可以参考下哈
    2013-04-04
  • JavaScript 里的类数组对象

    JavaScript 里的类数组对象

    这篇文章主要介绍了JavaScript 里的类数组对象的相关资料,需要的朋友可以参考下
    2015-04-04
  • javascript 关闭IE6、IE7

    javascript 关闭IE6、IE7

    通过javascript关闭浏览器的时候,“一般”会弹出系统的默认提示框,提示用户是否关闭浏览器,这可以通过javascript解决,但是IE6,IE7解决的办法是不一样的
    2009-06-06
  • JS效率个人经验谈(8-15更新),加入range技巧

    JS效率个人经验谈(8-15更新),加入range技巧

    JS效率个人经验谈(8-15更新),加入range技巧...
    2007-01-01
  • Webpack自动清理打包目录的实现

    Webpack自动清理打包目录的实现

    本文主要介绍了Webpack自动清理打包目录的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-01-01
  • js截取字符串的两种方法及区别详解

    js截取字符串的两种方法及区别详解

    本文是对js截取字符串的两种方法及区别进行了详细的介绍,需要的朋友可以过来参考下,希望对大家有所帮助
    2013-11-11
  • 封装微信小程序http拦截器过程解析

    封装微信小程序http拦截器过程解析

    这篇文章主要介绍了封装微信小程序http拦截器过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-08-08

最新评论