一文网尽关于大文件(分片)上传你需要知道的所有前置知识点

分片上传知识点

🚩 前端大文件上传和下载(分片上传),站内跳转

1 XMLHttpRequest.upload

XMLHttpRequest.upload 属性返回一个 XMLHttpRequestUpload对象,用来表示上传的进度。这个对象是不透明的,但是作为一个XMLHttpRequestEventTarget,可以通过对其绑定事件来追踪它的进度。

事件 相应属性的信息类型
onloadstart 获取开始
onprogress 数据传输进行中
onabort 获取操作终止
onerror 获取失败
onload 获取成功
ontimeout 获取操作在用户规定的时间内未完成
onloadend 获取完成(不论成功与否)



2 formData

FormData 接口提供了一种表示表单数据的键值对 key/value 的构造方式,并且可以轻松的将数据通过XMLHttpRequest.send() 方法发送出去,本接口和此方法都相当简单直接。

  • 如果送出时的编码类型被设为 multipart/form-data,它会使用和表单一样的格式。

  • 如果你想构建一个简单的GET请求,并且通过<form>的形式带有查询参数,可以将它直接传递给URLSearchParams。

  • 实现了 FormData 接口的对象可以直接在for...of结构中使用,而不需要调用entries() : for (var p of myFormData) 的作用和 for (var p of myFormData.entries()) 是相同的。


2.1 使用

new FormData()


2.2 方法

方法名 描述
FormData.append() 向 FormData 中添加新的属性值,FormData 对应的属性值存在也不会覆盖原值,而是新增一个值,如果属性不存在则新增一项属性值。
FormData.delete() 从 FormData 对象里面删除一个键值对。
FormData.entries() 返回一个包含所有键值对的iterator对象。
FormData.get() 返回在 FormData 对象中与给定键关联的第一个值。
FormData.getAll() 返回一个包含 FormData 对象中与给定键关联的所有值的数组。
FormData.has() 返回一个布尔值表明 FormData 对象是否包含某些键。
FormData.keys() 返回一个包含所有键的iterator对象。
FormData.set() 给 FormData 设置属性值,如果FormData 对应的属性值存在则覆盖原值,否则新增一项属性值。
FormData.values() 返回一个包含所有值的iterator对象。

2.3 为什么只用formData(multipart/form-data)进行上传大文件

🚩 详见文件常见传输数据格式 【HTTP】Content-Type 与 MIME,站内跳转

application/x-www-form-urlencoded 是把数据使用 url编码 后传送给后端,不适合用于传输大型二进制数据或者包含非ASCII字符的数据,
application/json 得到的只是一个描述性JSON对象,根本就不是一个文件对象。
如果说一定得需要用 json 来传递的话,那么就必须得把这个原生的 file 对象进行转码,例如:base64,然后后端在接收的时候按照 json 来解析,获取那一段字符串之后重新转码生成图像文件,过程确实繁琐了。




3 File对象

File 对象提供有关文件的信息,并允许网页中的 JavaScript 读写文件。

File 对象是特殊类型的 Blob,且可以用在任意的 Blob 类型的 context 中。比如说, FileReader, URL.createObjectURL(), createImageBitmap() (en-US), 及 XMLHttpRequest.send() 都能处理 Blob 和 File。


3.1 属性

属性 是否只读 描述
File.lastModified 只读 返回当前 File 对象所引用文件最后修改时间,自 UNIX 时间起始值(1970 年 1 月 1 日 00:00:00 UTC)以来的毫秒数。
File.lastModifiedDate(已弃用) 只读 返回当前 File 对象所引用文件最后修改时间的 Date 对象。
File.name 只读 返回当前 File 对象所引用文件的名字。
File.size 只读 返回文件的大小。File.webkitRelativePath 只读 非标准返回 File 相关的 path 或 URL。
File.type 只读 返回文件的 多用途互联网邮件扩展类型(MIME Type)

3.2 方法

Blob.slice([start[, end[, contentType]]])

返回一个新的 Blob 对象,它包含有源 Blob 对象中指定范围内的数据。




4 FileList对象

一个 FileList 对象通常来自于一个 HTML<input>元素的 files 属性,你可以通过这个对象访问到用户所选择的文件。该类型的对象还有可能来自用户的拖放操作,查看 DataTransfer (en-US) 对象了解详情。


4.1 属性:length

FileList是一个类数组对象,每个成员都是一个 File对象 实例,通过.length来获取当前类表中的文件数量

ps: 类数组也可以用数组解构的方式


4.2 方法:item()

根据给定的索引值,返回 FileList 对象中对应的 File 对象。也可以直接数组索引获取,因为是类数组。

// 遍历所有文件
for (var i = 0; i < files.length; i++) {
  // 取得一个文件
  file = files.item(i);
  // 这样也行
  file = files[i];
  // 取得文件名
  alert(file.name);
}



5 input 按钮上传按钮(上传相关)

带有 type="file" 的 <input type="file"> 元素允许用户可以从他们的设备中选择一个或多个文件。选择后,这些文件可以使用提交表单的方式上传到服务器上,或者通过 Javascript 代码和文件 API 对文件进行操作。

属性 描述
value表示已选择文件的路径字符串
事件 change 和 input
支持的公共属性 required
附加属性 accept、capture 和 multiple
IDL 属性 files 和 value
DOM接口 HTMLInputElement
方法 select()

5.1 值

value 为选择文件的路径,格式为字符串,默认为空串"",使用.value表示选中文件列表中的第一个。如果是开启multiple属性选择多个文件,可以通过ELEMENT节点.files来访问 FileList

注意 为了安全,值的路径显示为C:\fakepath\,而非真实路径


5.2 事件

当值发生改变时,触发这两个事件。input事件:输输入框内容发生改变时就会触发;change事件:输入框内容发生改变,并且输入框失去焦点时触发


5.3 附加属性

除了input公共方法,

5.3.1 accept属性

accept属性是一个字符串,它定义了文件 input 应该接受的文件类型。这个字符串是一个以逗号为分隔的唯一文件类型说明符列表(见下面)。

<input
  type="file"
  accept=".doc,.docx,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document"
/>

PS:唯一文件类型说明符列表

  • 一个以英文句号(“.”)开头的合法的不区分大小写的文件名扩展名。例如:.jpg、.pdf 或 .doc。
  • 一个不带扩展名的 MIME 类型字符串。
  • 字符串 audio/*,表示“任何音频文件”。
  • 字符串 video/*,表示“任何视频文件”。
  • 字符串 image/*,表示“任何图片文件”。

accept 属性的值是包含一个或多个(用逗号分隔)唯一文件类型说明符的字符串。例如,一个文件选择器需要能被表示成一张图片的内容,包括标准的图片格式和 PDF 文件,大概是这样的:

<input type="file" accept="image/*,.pdf" />

5.3.2 capture属性

capture 属性是一个字符串,如果 accept (en-US) 属性指出了 input 是图片或者视频类型,则它指定了使用哪个摄像头去获取这些数据。不作展开


5.3.3 multiple属性

multiple属性开启后允许用户选择多个文件


5.3.4 IDL 属性(files 和 value)

  1. files
    被选择的文件以 HTMLInputElement.files 属性返回,它是包含一系列 File 对象的 FileList 对象。FileList是一个类数组对象,每个成员都是一个 File 实例。包含

    所有现代浏览器中读写 HTMLInputElement.files 的值,不存在兼容性问题。

    属性 描述
    name 文件名。
    lastModified 一个数字,指定文件最后一次修改的日期和时间,以Unix时间戳表示。
    lastModifiedDate 已弃用 一个 Date 对象,表示文件最后一次修改的日期和时间。这被弃用,并且不应使用。使用 lastModified 作为替代。但是目前仍能访问
    size 以字节数为单位的文件大小。
    type 文件的 MIME 类型。
    webkitRelativePath 非标准 一个字符串,指定了相对于在目录选择器中选择的基本目录的文件路径(即,一个设置了 webkitdirectory 属性的 file 选择器)。这是非标准的,应该谨慎使用。
  2. value 同上面的 “值”




6 FileReader 对象

FileReader 对象允许 Web 应用程序异步读取存储在用户计算机上的文件(或原始数据缓冲区)的内容,使用 File 或 Blob 对象指定要读取的文件或数据。

6.1 属性

属性 是否只读 描述
FileReader.error 只读 一个DOMException,表示在读取文件时发生的错误。
FileReader.readyState 只读 表示FileReader状态的数字,EMPTY 0 还没有加载任何数据。LOADING 1 数据正在被加载。DONE 2 已完成全部的读取请求。
FileReader.result 只读 文件的内容。该属性仅在读取操作完成后才有效,数据的格式取决于使用哪个方法来启动读取操作。

6.2 事件

备注: 因为 FileReader 继承自EventTarget,所以所有这些事件也可以通过addEventListener方法使用。

事件 描述
FileReader.onabort 处理abort事件。该事件在读取操作被中断时触发。
FileReader.onerror (en-US) 处理error事件。该事件在读取操作发生错误时触发。
FileReader.onload 处理load事件。该事件在读取操作完成时触发。
FileReader.onloadstart 处理loadstart事件。该事件在读取操作开始时触发。
FileReader.onloadend 处理loadend事件。该事件在读取操作结束时(要么成功,要么失败)触发。
FileReader.onprogress 处理progress事件。该事件在读取Blob时触发。

6.3 方法

方法 描述
FileReader.abort() 中止读取操作。在返回时,readyState属性为DONE。
FileReader.readAsArrayBuffer() 开始读取指定的 Blob中的内容,一旦完成,result 属性中保存的将是被读取文件的 ArrayBuffer 数据对象。
FileReader.readAsBinaryString() 非标准 开始读取指定的Blob中的内容。一旦完成,result属性中将包含所读取文件的原始二进制数据。
FileReader.readAsDataURL() 开始读取指定的Blob中的内容。一旦完成,result属性中将包含一个data: URL 格式的 Base64 字符串以表示所读取文件的内容。对于图片文件,这个字符串可以用于元素的 src 属性。注意,这个字符串不能直接进行 Base64 解码,必须把前缀 data:/;base64 ,从字符串里删除以后,再进行解码。
FileReader.readAsText() 开始读取指定的Blob中的内容。一旦完成,result属性中将包含一个字符串以表示所读取的文件内容。该方法的第一个参数是代表文件的 Blob 实例,第二个参数是可选的,表示文本编码,默认为 UTF-8。



7 URL.createObjectURL()

URL.createObjectURL() 静态方法会创建一个 DOMString,其中包含一个表示参数中给出的对象的 URL。这个 URL 的生命周期和创建它的窗口中的 document 绑定。这个新的 URL 对象表示指定的 File 对象或 Blob 对象。

示例

objectURL = URL.createObjectURL(object);

object为用于创建 URL 的 File 对象、Blob 对象或者 MediaSource 对象。

返回一个DOMString包含了一个对象 URL,该 URL 可用于指定源 object的内容。

内存管理:在每次调用 createObjectURL() 方法时,都会创建一个新的 URL 对象,即使你已经用相同的对象作为参数创建过。当不再需要这些 URL 对象时,每个对象必须通过调用 URL.revokeObjectURL() 方法来释放。虽然浏览器也会自动释放,但是手动释放掉以获得最佳性能和内存使用状况




8 Base64

Base64 是一种基于64个可打印字符来表示二进制数据的表示方法。可以将图片转成base64,可以减少 HTTP 请求也可以将字符串进行解码和编码。

相关api 描述
atob() 解码,解码一个 Base64 字符串;
btoa() 编码,从一个字符串或者二进制数据编码一个 Base64 字符串。
let encodedData = window.btoa("Hello, world"); // 编码,得到'SGVsbG8sIHdvcmxk'
let decodedData = window.atob(encodedData); // 解码,得到'Hello, world'


9 DataURL

Data URL,即前缀为 data: 协议的 URL,其允许内容创建者向文档中嵌入小文件。它们之前被称作“data URI”,直到这个名字被 WHATWG 弃用。

9.1 语法

Data URL 由四个部分组成:前缀(data:)、指示数据类型的 MIME 类型、如果非文本则为可选的 base64 标记、数据本身:

如果数据是文本类型,你可以直接将文本嵌入(根据文档类型,使用合适的实体字符或转义字符)。否则,你可以指定 base64 来嵌入 base64 编码的二进制数据。你可以在这里和这里找到更多关于 MIME 类型的信息。

data:[<mediatype>][;base64],<data>


9.2 示例

  1. data:,Hello%2C%20World!
    简单的 text/plain 类型数据。注意逗号如何百分号编码为 %2C,空格字符如何编码为 %20。

  2. data:text/plain;base64,SGVsbG8sIFdvcmxkIQ%3D%3D
    上一条示例的 base64 编码版本

  3. data:text/html,%3Ch1%3EHello%2C%20World!%3C%2Fh1%3E
    一个 HTML 文档源代码 <h1>Hello, World</h1>

  4. data:text/html,%3Cscript%3Ealert%28%27hi%27%29%3B%3C%2Fscript%3E
    带有 <script>alert('hi');</script> 的 HTML 文档,用于执行 JavaScript 警告。注意,需要闭合的 script 标签。


9.3 给数据作 base64 编码

Base64 是一组二进制到文本的编码方案,通过将其转换为 radix-64 表示形式,以 ASCII 字符串格式表示二进制数据。通过仅由 ASCII 字符组成,base64 字符串通常是 url 安全的,这就是为什么它们可用于在 Data URL 中编码数据。



10 不同格式之间互相转换

10.1 File对象转Base64:

const file = e.target.files;
const fr = new FileReader();
fr.readAsDataURL(file[0]);
fr.onload = e => {
  console.log(e.target.result);
};

10.2 ArrayBuffer转blob

const blob = new Blob([new Uint8Array(buffer, byteOffset, length)]);

10.3 ArrayBuffer转base64

const base64 = btoa(String.fromCharCode.apply(null, new Uint8Array(arrayBuffer)));

10.4 base64转blob

const base64toBlob = (base64Data, contentType, sliceSize) => {
  const byteCharacters = atob(base64Data);
  const byteArrays = [];

  for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
    const slice = byteCharacters.slice(offset, offset + sliceSize);

    const byteNumbers = new Array(slice.length);
    for (let i = 0; i < slice.length; i++) {
      byteNumbers[i] = slice.charCodeAt(i);
    }

    const byteArray = new Uint8Array(byteNumbers);
    byteArrays.push(byteArray);
  }

  const blob = new Blob(byteArrays, { type: contentType });
  return blob;
};

10.5 blob转ArrayBuffer

function blobToArrayBuffer(blob) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = () => resolve(reader.result);
    reader.onerror = () => reject;
    reader.readAsArrayBuffer(blob);
  });
}

10.6 blob转base64

function blobToBase64(blob) {
  return new Promise(resolve => {
    const reader = new FileReader();
    reader.onloadend = () => resolve(reader.result);
    reader.readAsDataURL(blob);
  });
}

10.7 blob转Object URL

const objectUrl = URL.createObjectURL(blob);

10.8 blob转成text文本

async () => {
  return await new Response(blob).text();
};

10.9 Buffer转JSON

let bufferDatas = Buffer.from("woshibufferwenjian");
console.log(bufferDatas);
let json = JSON.stringify(bufferDatas, null, 2);
console.log(json);

10.10 JSON转Buffer

let bufferFile = Buffer.from(JSON.parse(json).data);
console.log(bufferFile);

10.11 Buffer转UTF-8字符串

bufferFile.toString("utf8");
posted @ 2023-03-03 22:51  wanglei1900  阅读(388)  评论(0编辑  收藏  举报