实现大文件切片上传

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

前言 🍊🍊


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


文件是如何上传的?


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

  • 基于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天前
|
计算机视觉 Python
Opencv学习笔记(一):如何将得到的图片保存在指定目录以及如何将文件夹里所有图片以数组形式输出
这篇博客介绍了如何使用OpenCV库在Python中将图片保存到指定目录,以及如何将文件夹中的所有图片读取并以数组形式输出。
95 0
Opencv学习笔记(一):如何将得到的图片保存在指定目录以及如何将文件夹里所有图片以数组形式输出
|
1月前
|
Java
java实现从HDFS上下载文件及文件夹的功能,以流形式输出,便于用户自定义保存任何路径下
java实现从HDFS上下载文件及文件夹的功能,以流形式输出,便于用户自定义保存任何路径下
52 2
java实现从HDFS上下载文件及文件夹的功能,以流形式输出,便于用户自定义保存任何路径下
|
4月前
分享:根据批量的图片文件名,如何在电脑里一次性查找多张图片,复制并保存到新的文件夹
本文介绍了一款批量文件处理软件,用于快速查找和管理大量图片。通过下载链接提供软件,用户可执行以下操作:搜索并复制特定文件名的图片,从大型图库中筛选目标图片至指定位置,或按文件名批量删除图片。软件支持完全匹配、模糊查找和格式限定等查找方式。使用后能显著提升图片整理效率,节省时间。
516 3
|
4月前
|
Web App开发
PanTools v1.0.27 多网盘批量管理、遍历分享、转存、重命名、复制...
一款针对多个热门网盘的文件管理、批量分享、批量转存、批量重命名、批量复制、批量链接检测、跨账号移动文件、多账号文件搜索等,支持不同网盘的不同账号的资源文件操作。适用于网站站长、资源爱好者、网盘拉新等,对于管理名下具有多个网盘多个账号具有实用的效果。
111 0
|
6月前
分享:批量多目录图片如何转换PDF,一次性转换多级目录批量的PDF的转换,合并,输出另存等问题,图片转PDF文件,批量图片转PDF文件,多级目录的图片转PDF文件,并且保存到不同的地方,全部搞定
本文介绍了如何高效地将图片转换为PDF,包括单张、多张及多级目录下的图片转换和合并。提供了软件下载链接(百度网盘、腾讯云盘),软件操作简便,支持保存原目录或自定义新目录。转换选项包括单个文件、多个文件夹单独转换以及合并转换。用户可通过双击路径访问源图片和转换结果。该工具特别解决了多级目录图片批量转换的难题,实现保存地址的自由设定,满足不同业务需求。
370 0
|
6月前
|
Windows
推荐:如何批量根据PDF文件名批量查找PDF文件,复制到指定地方保存,通过文件名批量复制文件,按照文件名批量复制文件,根据文件名批量提取文件
该文介绍了一个批量查找PDF文件(不限于找PDF)的工具,用于在多级文件夹中快速查找并复制特定文件。通过下载提供的软件,用户可以加载PDF库,输入文件名列表,设置操作参数(如保存路径、复制或删除)及搜索模式。软件能高效执行,例如在1.1秒内完成对数千文件中的37个目标文件的复制,显著提升了工作效率,避免了手动逐个查找和复制的繁琐。
585 0
|
6月前
|
存储 定位技术 Python
批量将文件名称符合要求的文件自动复制到新文件夹:Python实现
批量将文件名称符合要求的文件自动复制到新文件夹:Python实现
100 2
|
JSON 数据格式
批量遍历指定类型的文件及文件夹,并将其复制到新的文件夹
批量遍历指定类型的文件及文件夹,并将其复制到新的文件夹
|
前端开发
前端上传文件保存到变量中
前端上传文件保存到变量中
前端上传文件保存到变量中