实现大文件切片上传

简介: 实现大文件切片上传

前言 🍊🍊


在上一篇文章中我们讲解了如何进行图片的一个压缩处理,里面涉及到很多与文件相关的知识,我们在实际项目开发中可能会用到文件上传操作,今天就来学习一下如何实现文件的切片上传。


文件是如何上传的?


首先我们要知道一般上传文件有两种方式:

  • 基于FormData的格式来进行文件的上传
  • 基于Base64的格式来进行上传

这两种方式上传各有优缺点:

Base64上传

  • 优点:
  • 简单易用:将文件转换为Base64字符串,然后将其作为文本数据发送,不需要额外的表单数据。 *  跨平台兼容:Base64是一种文本格式,可以在任何支持文本传输的平台上使用。 *  不需要额外的文件流处理:Base64数据可以直接包含在请求的主体中,不需要使用文件流进行处理。
  • 缺点:
  • base64上传的最大缺点就是他会是原本的文件的体积增大约1/3,这对于大文件上传尤其不利
  • 由于文件的体积增大,上传的效率自然也就变低

FormData上传

  • 优点:
  • 支持多文件上传:通过FormData可以同时上传多个文件,方便批量上传。
  • 文件流处理:FormData可以使用文件流的方式上传文件,适用于大型文件或流式传输的场景。
  • 可以携带其他表单数据:FormData可以同时携带其他表单数据,方便与文件相关的其他数据一起传输。
  • 缺点:
  • 使用稍复杂:相比Base64上传,使用FormData上传需要创建一个FormData对象,然后将文件和其他表单数据附加到该对象上。
  • 需要服务器端处理:使用FormData上传需要服务器端进行相应的解析和处理,提取上传的文件和表单数据。


了解一些文件相关的知识:🎮🎮


我们经常能够看到一些文件相关的知识例如 FlieReader,File,Blob等等相关的知识,其实可以用一张图来说明:

image.png

Blob

Blob 全称为 binary large object ,即二进制大对象。blob对象本质上是js中的一个对象,里面可以储存大量的二进制编码格式的数据。

blob对象上面一般会有两个属性:

size:Blob对象中所包含数据的大小(字节);

type:字符串,认为该Blob对象所包含的 MIME 类型。如果类型未知,则为空字符串。

同时我们应该要注意到Blob 对象内置了 slice() 方法用来将 blob 对象分片

start:设置切片的起点,即切片开始位置。默认值为 0,这意味着切片应该从第一个字节开始;

end:设置切片的结束点,会对该位置之前的数据进行切片。默认值为blob.size; 这样我们就可以通过slice方法来完成对blob数据的切片操作,切片之后的数据还会返回一个blob类型的数据。

File类型

Flie类型其实是特殊类型的Blob类型

当我们点击input中选择文件之后会返回一个FlieList对象

也可以通过拖拽操作生成的 DataTransfer 对象;


FileReader对象


使用FileReader对象的目的就是因为Blob中的数据是无法读取的,因此我们要通过FileReader中的方法来转换为我们想要读取的数据类型

  • readAsArrayBuffer(file):按字节读取文件内容,结果用ArrayBuffer对象表示
  • readAsBinaryString(file):按字节读取文件内容,结果为文件的二进制串
  • readAsDataURL(file):读取文件内容,结果用data:url的字符串形式表示
  • readAsText(file,encoding):按字符读取文件内容,结果用字符串形式表示

在知道这些基础的知识之后我们就可以尽心大文件的切片上传操作


大文件的切片上传 🍯🍯


首先大家肯定会有疑问:什么是切片上传?

故名思意就是将一些大的文件切成一份一份的,来进行分开的上传操作,我们可以自定义切片的大小,然后后端在拿到数据之后在拼接起来。将其组装成为一个数据。

由于代码稍微有一点多,因此我们将其拆分成及部分来看

((doc) => {
  const selectFile = doc.querySelector("#selectFile");
  const progress = doc.querySelector("#progress");
  const uploadFile = doc.querySelector("#uploadFile");
  // 绑定点击事件
  function BindEvent() {
    selectFile.addEventListener("change", selectFuc);
    uploadFile.addEventListener("click", uploadSlice);
  }
   ....
   BindEvent();
  })(document)
  • 首先我们写一个立即执行函数,将一些初始化操作先完成,我们首先获取上传文件的input框,以及进度条和上传按钮的DOM元素。
  • 然后我们给元素绑定点击事件,单独将这部分抽离出来,是整体看起来更加的规范。
const UPLOAD_TYPE = {
  "image/png": "png",
  "image/jpg": "jpg",
  "image/jpeg": "jpeg",
  "video/mp4": "mp4",
};
 function selectFuc(e) {
    const File = e.target.files[0];
    console.log(File);
    if (!UPLOAD_TYPE[File.type]) {
      alert("格式不合要求");
      this.value = "";
      return;
    }
  • 然后我们完成校验函数的封装,当然这里我们只是进行了一个简单的封装,对文件的类型进行一个简单的校验。如果想要上传的文件按不符合要求,那么就弹出弹框提示,并且将input中的value赋值为空。
  • 这里我们可以通过e.target.file[0]来获取上传的元素
  • 我们这里将一些我们允许上传的文件单独写成了一个对象,这也是模块化的体现。
  // 上传函数
  async function uploadSlice() {
      //获取input选择上传的文件
    const file = selectFile.files[0];
    if (!file) {
      alert("上传内容步能为空");
      return;
    }
    const { name, type, size } = file;
    //  定义切片的大小
    const chunckSize = 64 * 1024; // 当前文件上传的大小
    let currentSize = 0;
    progress.max = size;
    while (currentSize < size) {
      // 切片切出来的元素
      const FileChunk = file.slice(currentSize, currentSize + chunckSize);
      console.log(FileChunk);
      const Form = createFormData({ name, size, type, FileChunk });
      await axios.get("http://localhost:3000/upload", Form);
      currentSize += FileChunk.size;
      progress.value = currentSize;
    }
  }

然后我们就要封装最重要的函数:切片上传函数

  • 首先我们首先判断是否选择了要上传的元素,如果没有选择要上传的元素,则弹出弹框并且return。
  • 然后我们通过解构将file中的常用属性解构出来
  • 紧接着我们设置切片的大小,这个大小可以自己选择,然后还要定义一个变量,保存的是当前的已经上传的元素的大小,初始值为0
  • 我们这里给进度条的DOM元素设置max为元素的大小,这与之后的progress的value值要进行配合,这样我们可以看清楚上传的进度
  • 然后创建Form元素,等会同样这里我们也封装了一个函数,等一会我们在展开说
  • 然后我们就要使用silce来进行切片,返回的是被切成小段的元素,有趣的是,如果将这一段通过FileReader中的方法转换为base64的格式,同样可以显示出来图片,只不过是被裁掉了一截。思考一下,根据这个我们可以实现什么?
  • 然后我们通过axios给后端发送请求,注意这里我的后端就是通过express简单的搭了一个,感兴趣的同学也可以搞一个,但是这里我们只是学习一下思路,这个不是重点,我就不展开来讲。
  • 然后每次发送完请求之后给currentSize加上切片上传的尺寸,表明当前已经完成的部分,然后给进度条的vaue赋值为currentSize。

封装创建FormData函数:

// 限制文件上传的类型
  // 创建FormData
  function createFormData({ name, type, size, currentSize }) {
    const Form = new FormData();
    Form.append("name", name);
    Form.append("type", type);
    Form.append("size", size);
    Form.append("currentSize", currentSize);
    return Form;
  }

这部分其实比较好理解,就是单独封装了一个函数,用来创建FormData,然后通过append讲这些属性追加进去,最后返回通过axios发送给后端。


总结:🤙🤙


通过这次学习,我们掌握了文件相关的知识,了解了文件的传输形式(FormData,base64),并且我们学习了如何进行大文件的切片上传,使自己有很多收获。

相关文章
|
20天前
|
监控 Java Serverless
函数计算产品使用问题之对于OSS打包的zip的保存目录,该如何操作
阿里云Serverless 应用引擎(SAE)提供了完整的微服务应用生命周期管理能力,包括应用部署、服务治理、开发运维、资源管理等功能,并通过扩展功能支持多环境管理、API Gateway、事件驱动等高级应用场景,帮助企业快速构建、部署、运维和扩展微服务架构,实现Serverless化的应用部署与运维模式。以下是对SAE产品使用合集的概述,包括应用管理、服务治理、开发运维、资源管理等方面。
分享:根据批量的图片文件名,如何在电脑里一次性查找多张图片,复制并保存到新的文件夹
本文介绍了一款批量文件处理软件,用于快速查找和管理大量图片。通过下载链接提供软件,用户可执行以下操作:搜索并复制特定文件名的图片,从大型图库中筛选目标图片至指定位置,或按文件名批量删除图片。软件支持完全匹配、模糊查找和格式限定等查找方式。使用后能显著提升图片整理效率,节省时间。
分享:批量多目录图片如何转换PDF,一次性转换多级目录批量的PDF的转换,合并,输出另存等问题,图片转PDF文件,批量图片转PDF文件,多级目录的图片转PDF文件,并且保存到不同的地方,全部搞定
本文介绍了如何高效地将图片转换为PDF,包括单张、多张及多级目录下的图片转换和合并。提供了软件下载链接(百度网盘、腾讯云盘),软件操作简便,支持保存原目录或自定义新目录。转换选项包括单个文件、多个文件夹单独转换以及合并转换。用户可通过双击路径访问源图片和转换结果。该工具特别解决了多级目录图片批量转换的难题,实现保存地址的自由设定,满足不同业务需求。
|
3月前
|
Windows
推荐:如何批量根据PDF文件名批量查找PDF文件,复制到指定地方保存,通过文件名批量复制文件,按照文件名批量复制文件,根据文件名批量提取文件
该文介绍了一个批量查找PDF文件(不限于找PDF)的工具,用于在多级文件夹中快速查找并复制特定文件。通过下载提供的软件,用户可以加载PDF库,输入文件名列表,设置操作参数(如保存路径、复制或删除)及搜索模式。软件能高效执行,例如在1.1秒内完成对数千文件中的37个目标文件的复制,显著提升了工作效率,避免了手动逐个查找和复制的繁琐。
|
3月前
|
弹性计算 运维 Shell
返回目录中所有JPG图像的文件名列表
返回目录中所有JPG图像的文件名列表
合并多个文件的内容到一个文件
合并多个文件的内容到一个文件
|
3月前
|
存储 定位技术 Python
批量将文件名称符合要求的文件自动复制到新文件夹:Python实现
批量将文件名称符合要求的文件自动复制到新文件夹:Python实现
|
Python
Python 文件操作(创建、读取、追加、图片视频读取)
Python 文件操作(创建、读取、追加、图片视频读取)
104 0