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大文件上传内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • JavaScript文件上传的常见问题整理

    文件上传:<input type="file" /> (IE9及以下不支持下面这些功能,其它浏览器最新版本均已支持.) 1.允许上传文件数量 允许选择多个文件: <input type="file" multiple> 只允许上传一个文件: <input  type="file" single> 2.上传指定的文件格式 <input type="file" accept="i

  • JS实现可恢复的文件上传示例详解

    目录 正文 不太实用的进度事件 算法 server.js uploader.js index.html 正文 使用 fetch 方法来上传文件相当容易. 连接断开后如何恢复上传?这里没有对此的内建选项,但是我们有实现它的一些方式. 对于大文件(如果我们可能需要恢复),可恢复的上传应该带有上传进度提示.由于 fetch 不允许跟踪上传进度,我们将会使用 XMLHttpRequest. 不太实用的进度事件 要恢复上传,我们需要知道在连接断开前已经上传了多少. 我们有 xhr.upload.onpro

  • JS文件上传时如何使用MD5加密

    目录 JS文件上传使用MD5加密 什么是MD5? MD5怎么用? 前端中md5的用法 md5的使用方法 JS文件上传使用MD5加密 什么是MD5? MD5信息摘要算法(英语:MD5 Message-Digest Algorithm),一种被广泛使用的密码散列函数,可以产生出一个128位(16字节)的散列值(hash value),用于确保信息传输完整一致.(MD5 百度百科) 简而言之,就是对上传文件进行加密. MD5怎么用? 在页面中使用需下载依赖包,yarn spark-md5或npm in

  • JavaScript进阶之前端文件上传和下载示例详解

    目录 文件下载 1.通过a标签点击直接下载 2.open或location.href 3.Blob和Base64 文件上传 文件上传思路 File文件 上传单个文件-客户端 上传文件-服务端 多文件上传-客户端 大文件上传-客户端 大文件上传-服务端 文件下载 1.通过a标签点击直接下载 <a href="https:xxx.xlsx" rel="external nofollow" download="test">下载文件</

  • JavaScript大文件上传的处理方法之切片上传

    目录 前言 切片后上传 生成hash 文件秒传 暂停上传 中断请求示例 添加暂停上传功能 恢复上传 添加功能总结 前言 本篇介绍了切片上传的基本实现方式(前端),以及实现切片上传后的一些附加功能,切片上传原理较为简单,代码注释比较清晰就不多赘述了,后面的附加功能介绍了实现原理,并贴出了在原本代码上的改进方式.有什么错误希望大佬可以指出,感激不尽. 切片后上传 切片上传的原理较为简单,即获取文件后切片,切片后整理好每个切片的参数并发请求即可. 下面直接上代码: HTML <template> &

  • 原生JS实现文件上传

    本文实例为大家分享了JS实现文件上传的具体代码,供大家参考,具体内容如下 一.目的: 实现上传图片功能 二.效果: 三.思路: 用input标签自带的上传,先隐藏掉,给上传按钮添加点击事件,绑定input的点击事件 四.代码: //html <input ref="img-upload-input" class="img-upload-input" type="file" accept=".png, .jpg" @cha

  • Vue+NodeJS实现大文件上传的示例代码

    目录 整体思路 项目演示 前端界面 文件切片 hash计算 查询切片状态 切片上传(断点续传) 文件总体上传进度 合并文件 优化 请求并发数控制 hash值计算优化 常见的文件上传方式可能就是new一个FormData,把文件append进去以后post给后端就可以了.但如果采用这种方式来上传大文件就很容易产生上传超时的问题,而且一旦失败还得从新开始,在漫长的等待过程中用户还不能刷新浏览器,不然前功尽弃.因此这类问题一般都是通过切片上传. 整体思路 将文件切成多个小文件 hash计算,需要计算一

  • SpringBoot整合腾讯云COS对象存储实现文件上传的示例代码

    目录 1.开通腾讯云对象存储服务 2.创建存储桶 3.密钥管理,新建密钥 4.yml配置密钥.COS信息 5.COSConfig配置类 6.COS文件上传工具类 7.Controller测试上传接口: 8.PostMan接口调用 9.浏览器预览效果 企业级项目开发中都会有文件.图片.视频等文件上传并能够访问的场景,对于初学者Demo可能会直接存储在应用服务器上:对于传统项目可能会单独搭建FastDFS.MinIO等文件服务来实现存储,这种方案可能对于企业成本较小,但缺点也是很多,例如:1.增加技

  • JavaScript Base64 作为文件上传的实例代码解析

    例如我们用某些 裁剪插件 得到的图片是 <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAkCAYAAABIdFAMAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAHhJREFUeNo8zjsOxCAMBFB/ KEAUFFR0Cbng3nQPw68ArZdAlOZppPFIBhH5EAB8b+Tlt9MYQ6i1BuqFaq1CKSVcxZ2Acs6406

  • vue中实现图片和文件上传的示例代码

    html页面 <input type="file" value="" id="file" @change='onUpload'>//注意不能带括号 js代码 methods: { //上传图片 onUpload(e){ var formData = new FormData(); f ormData.append('file', e.target.files[0]); formData.append('type', 'test');

  • Java实现一个简单的文件上传案例示例代码

    Java实现一个简单的文件上传案例 实现流程: 1.客户端从硬盘读取文件数据到程序中 2.客户端输出流,写出文件到服务端 3.服务端输出流,读取文件数据到服务端中 4.输出流,写出文件数据到服务器硬盘中 下面上代码 上传单个文件 服务器端 package FileUpload; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.Serve

  • GO语言实现文件上传的示例代码

    目录 前言 文件上传 表单操作 服务端操作 流程实现 小结 前言 最近在写一个文件上传的功能,现在来进行整理总结一下go语言如何上传文件的,本文主要分享一下golang实现文件上传的流程和具体代码,供大家参考,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助. 文件上传 表单操作 要使表单能够上传文件,需要添加form的enctype属性enctype="multipart/form-data",upload.html代码如下: <html> <head> &

  • 利用discuz实现PHP大文件上传应用实例代码

    对于确实需要改善论坛附件上传条件的朋友可以尝试将上面提及的参数在php.ini进行设置,以适应大文件上传的需要.同时别忘记在论坛的后台相应做附件限制的地方进行设置. 论坛主要有2个地方可以对附件上传的大小进行限制,级别从高到低依次为: 帖子相关---附件类型尺寸 用户组---附件相关 同时,下面提供一个配置指导,来源一些成功通过http上传大附件的朋友的提供,当然,由于大家的服务器配置情况以及网络情况不同,并不一定适用你的情况,可能很多地方需要参照修改: 打开php.ini, 参数 设置 说明

  • asp.net大文件上传解决方案实例代码

    以ASP.NET Core WebAPI 作后端 API ,用 Vue 构建前端页面,用 Axios 从前端访问后端 API ,包括文件的上传和下载. 准备文件上传的API #region 文件上传 可以带参数 [HttpPost("upload")] public JsonResult uploadProject(IFormFile file, string userId) { if (file != null) { var fileDir = "D:\\aaa"

  • java接收ios文件上传的示例代码

    本文实例为大家分享了java如何接收ios文件上传的具体代码,供大家参考,具体内容如下 ios Multipart/form-data POST请求java后台spring接口一直出错,搞了两天,终于解决了,积累下来 package com.xx.controller; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.Iterator

  • springMVC实现前台带进度条文件上传的示例代码

    项目框架采用spring+hibernate+springMVC如果上传文件不想使用flash那么你可以采用HTML5;截图前段模块是bootstarp框架;不废话直接来代码;spring-mvc配置文件;效果截图如下: 详细实现如下: 1.mvc-config.xml <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/s

随机推荐