首页 > 其他分享 >浅析实现大文件上传和断点续传

浅析实现大文件上传和断点续传

时间:2023-09-26 12:01:54浏览次数:39  
标签:断点续传 hash 文件 切片 file 上传 浅析 服务端

大文件上传:

前端部分:
核心是利用 Blob.prototype.slice 方法,和数组的 slice 方法相似,调用的 slice 方法可以返回原文件的某个切片。

  • 根据预先设置好的切片最大数量将文件切分为一个个切片,然后借助 http 的可并发性,同时上传多个切片。
  • 这样从原本传一个大文件,变成了同时传多个小的文件切片,可以大大减少上传时间。
  • 另外由于是并发,传输到服务端的顺序可能会发生变化,所以我们还需要给每个切片记录顺序。

服务端部分:
服务端接收到所有切片后合并切片。

问题1:何时合并切片,即切片什么时候传输完成?
前端在每个切片中都携带切片最大数量的信息,当服务端接受到这个数量的切片时自动合并,也可以额外发一个请求主动通知服务端进行切片的合并。
问题2:如何合并切片?
可以使用 nodejs 的 读写流(readStream/writeStream),将所有切片的流传输到最终文件的流里。

<template>
  <div>
    <input type="file" @change="handleFileChange" />
    <el-button @click="handleUpload">上传</el-button>
  </div>
</template>

<script>
+ const SIZE = 10 * 1024 * 1024; // 切片大小

export default {
  data: () => ({
    container: {
      file: null
    },
   data: []
  }),
  methods: {
    request() {},
    handleFileChange() {},
    // 生成文件切片
    createFileChunk(file, size = SIZE) {
     const fileChunkList = [];
      let cur = 0;
      while (cur < file.size) {
        fileChunkList.push({ file: file.slice(cur, cur + size) });
        cur += size;
      }
      return fileChunkList;
    },
   // 上传切片
    async uploadChunks() {
      const requestList = this.data
        .map(({ chunk,hash }) => {
          const formData = new FormData();
          formData.append("chunk", chunk);
          formData.append("hash", hash);
          formData.append("filename", this.container.file.name);
          return { formData };
        })
        .map(async ({ formData }) =>
          this.request({
            url: "http://localhost:3000",
            data: formData
          })
        );
      await Promise.all(requestList); // 并发切片
    },
    async handleUpload() {
      if (!this.container.file) return;
      const fileChunkList = this.createFileChunk(this.container.file);
      this.data = fileChunkList.map(({ file },index) => ({
        chunk: file,
        hash: this.container.file.name + "-" + index // 文件名 + 数组下标
      }));
      await this.uploadChunks();
    }
  }
};
</script>

当点击上传按钮时,调用 createFileChunk 将文件切片,切片数量通过文件大小控制,这里设置 10MB,也就是说 100 MB 的文件会被分成 10 个切片
createFileChunk 内使用 while 循环和 slice 方法将切片放入 fileChunkList 数组中返回
在生成文件切片时,需要给每个切片一个标识作为 hash,这里暂时使用文件名 + 下标,这样后端可以知道当前切片是第几个切片,用于之后的合并切片
随后调用 uploadChunks 上传所有的文件切片,将文件切片,切片 hash,以及文件名放入 FormData 中,再调用上一步的 request 函数返回一个 proimise,最后调用 Promise.all 并发上传所有的切片。

总结:

  • 前端上传大文件时使用 Blob.prototype.slice 将文件切片,并发上传多个切片,最后发送一个合并的请求通知服务端合并切片
  • 服务端接收切片并存储,收到合并请求后使用流将切片合并到最终文件
  • 原生 XMLHttpRequest 的 upload.onprogress 对切片上传进度的监听
  • 使用 Vue 计算属性根据每个切片的进度算出整个文件的上传进度

断点续传:

断点续传的原理在于前端/服务端需要记住已上传的切片,这样下次上传就可以跳过之前已上传的部分,有两种方案实现记忆的功能。

  • 前端使用 localStorage 记录已上传的切片 hash
  • 服务端保存已上传的切片 hash,前端每次上传前向服务端获取已上传的切片。

总结:

  • 使用 spark-md5 根据文件内容算出文件 hash
  • 通过 hash 可以判断服务端是否已经上传该文件,从而直接提示用户上传成功(秒传)
  • 通过 XMLHttpRequest 的 abort 方法暂停切片的上传
  • 上传前服务端返回已经上传的切片名,前端跳过这些切片的上传

 

参考文章:http://blog.ncmem.com/wordpress/2023/09/26/%e6%b5%85%e6%9e%90%e5%ae%9e%e7%8e%b0%e5%a4%a7%e6%96%87%e4%bb%b6%e4%b8%8a%e4%bc%a0%e5%92%8c%e6%96%ad%e7%82%b9%e7%bb%ad%e4%bc%a0/

欢迎入群一起讨论

 

标签:断点续传,hash,文件,切片,file,上传,浅析,服务端
From: https://www.cnblogs.com/songsu/p/17729790.html

相关文章

  • 大文件上传如何做断点续传
    断点续传是什么?断点续传(ResumableFileUpload)是一种文件上传的技术,它允许在上传过程中出现中断或失败的情况下,能够从中断的位置继续上传,而不需要重新上传整个文件。这在处理大文件或不稳定的网络连接时非常有用。断点续传的实现通常涉及以下几个关键概念和步骤:分片:将大文件分......
  • file文件上传后 添加水印 并且生成file文件 使用formData上传
    functionhecheng(){//创建一个canvasconstd2=testCanvas.getContext('2d');//准备图片1consturl=URL.createObjectURL(file.files[0]);varimg=docu......
  • windows系统上的github项目的上传和下载
    通过把远程仓库文件克隆下来,再添加自己需要上传的文件,再上传到远程仓库。 1、下载git工具:https://gitforwindows.org/下载安装之后,右键鼠标会出现两个新选项,分别为[GitGUIHere],[GitBashHere] 2、进入GitHub首页,点击Newrepository新建一个项目仓库Re......
  • Odoo自定义报表 - 浅析
    大家好,在Odoo(原OpenERP开源ERP)架构中,有自定义报表开发【CustomReportEngine】这一功能,但无论在海外还是国内的网站上很难找到相关的解释与介绍。所以,我们整理了相关开发介绍至本博文中。首先,需要讲解的是CustomReportEngine的机制。Odoo自定义报表架构是通过读取模块中re......
  • vue实现大文件切片上传、断点续传、并发数控制等
     一、上传按钮和进度条等<div><h2>上传文件</h2><divref="drag"class="drag"><inputclass="file"type="file"@change="handlerChange"/></div><el-progressstyle="......
  • 文件上传 切片与断点续传
    主要讲前端,后端使用node。会写一下后端的处理1.单个文件上传请求头为multipart/form-data数据为from-data格式letformData=newFormData();formData.append('file',_file);formData.append('filename',_file.name);然后使用post直接给后端。后端直接存......
  • Tomcat--文件上传--文件包含--(CVE-2017-12615)&&(CVE-2020-1938)
    Tomcat--文件上传--文件包含--(CVE-2017-12615)&&(CVE-2020-1938)复现环境采用Vulfocus靶场环境进行复现,搭建操作和文章参考具体搭建教程参考vulfocus不能同步的解决方法/vulfocus同步失败。CVE-2017-12615文件上传漏洞简介当存在漏洞的Tomcat运行在Windows/Linux主机上,且......
  • 大文件切片上传+断点续传解决方案-前后端实现
    上传文件大家应该都做过,前端直接把file文件传给后端就ok了,但是大文件这样传就会造成页面假死,体验极差。如果遇到网络不稳定的时候,中途上传失败的话,又要从头开始传,本来文件就大,还慢。所以今天我们用一种新方法-切片上传+断点续传前端实现:页面上很简单,我就放了进度条和一个上传文件......
  • PbootCMS附件上传报错UNKNOW: Code: 8192; Desc: stripos()
    PbootCMS附件上传报错UNKNOW:Code:8192;Desc:stripos(),具体显示如下图所示:解决方法:打开/core/function/file.php,找到以下代码:1if (stripos($types,$ext)!== false)改为如下代码:1if (stripos($types,chr($ext))!== false)......
  • springBoot上传文件时MultipartFile报空问题解决方法
    1.问题描述:之前用springMVC,转成springboot之后发现上传不能用。网上参考说是springboot已经有CommonsMultipartResolver了,但是我的上传后台接收的还是null。2.解决方法加入配置类importorg.springframework.context.annotation.Bean;importorg.springframework.context......