文件下载方式

1.a标签
要求资源是同源的,支持跨域下载看下文的Blob

  1. <a href='下载文件的url' download>点我下载</a>

2.window.open
会有一个打开tab页的过程,浏览器可以直接解析的会直接显示出来,不能解析的会下载

  1. window.open('目标url')
  2. 引申:
  3. window.open("webpage.htm", "_self");
  4. window.location.href = "webpage.htm";
  5. 都是在当前页面打开url
  6. // window.location.href 是一个属性,它会告诉你浏览器的当前URL位置。更改属性的值将重定向页面。
  7. // window.open()是一种方法,您可以将 URL 传递给要在新窗口中打开的 URL。

Data URI

  1. data:[<MIME type>][;charset=<charset>][;base64],<encoded data>

声明:参数+数据,逗号左边的是各种参数,右边的是数据。

【1】第①部分data: 协议头,它标识这个内容为一个 data URI 资源。
【2】第②部分MIME 类型(可选项):浏览器通常使用MIME类型(而不是文件扩展名)来确定如何处理文档;因此服务器设置正确以将正确的MIME类型附加到响应对象的头部是非常重要的。MIME类型对大小写不敏感,但是传统写法都是小写。

类型 描述 示例(语法:type/subtype 类型/子类型)
text 表明文件是普通文件,理论上是人类可读的 text/plain,text/html,text/css,text/javascript
image 表明文件某种是图像文件,gif动态图也属于image类型 image/gif,image/png,image/jpeg,image/bmp,image/webp,image/x-icon,image/vnd.microsoft.icon
audio 表明文件是某种音频文件 audio/midi,audio/mpeg,audio/webm,audio/ogg,audio/wav
video 表明文件是某种视频文件 video/webm,video/ogg
application 表明文件是某种二进制数据 application/octet-stream,application/pkcs12,application/vnd.mspowerpoint,application/xhtml+xml,application/xml,application/pdf

【3】第③部分 ;charset= 源文本的字符集编码方式,默认编码是 charset=US-ASCII, 即数据部分的每个字符都会自动编码为 %xx
【4】第④部分 [;] : 数据编码方式(默认US-ASCII,BASE64两种)
【5】第⑤部分 , 编码后的数据

Base64

Base64: 将数据用64个字符进行编码的方式,只要数据为二进制的都可以被编码,适用于文本,图片等。 原理:3×8 = 4×6 。 将原来每8bit,即一字节的,拆分成4个6bit的,再填0变成8bit,所以相当于 每3位变成了4位,增加了1/3的尺寸。 作用:编完码后,文本,图片都变成了流stream的感觉,可以用于传输

  1. <img width="40" height="30" src="data:image/jpg;base64,/9j/4QMZRXhpZgAASUkqAAgAAAAL...." />
  • atob base64 转 字符串
  • btoa base64编码
    1. window.atob('RnJ1aXQgQnJv');
    2. // 返回:'Fruit Bro

    base64转换为文件

    1. export function dataURLtoFile(dataurl, filename) {
    2. const arr = dataurl.split(',');
    3. const mime = arr[0].match(/:(.*?);/)[1];
    4. const bstr = atob(arr[1]);
    5. let n = bstr.length;
    6. const u8arr = new Uint8Array(n);
    7. while (n--) {
    8. u8arr[n] = bstr.charCodeAt(n);
    9. }
    10. return new File([u8arr], filename, { type: mime });
    11. }
    Uint8Array 数组类型表示一个8位无符号整型数组,创建时内容被初始化为0。创建完后,可以以对象的方式或使用数组下标索引的方式引用数组中的元素。

charCodeAt() 方法返回 0 到 65535 之间的整数,表示给定索引处的 UTF-16 代码单元。

  1. 不同索引情况下返回的 Unicode 值:
  2. "ABC".charCodeAt(0) // returns 65:"A"
  3. "ABC".charCodeAt(1) // returns 66:"B"
  4. "ABC".charCodeAt(2) // returns 67:"C"
  5. "ABC".charCodeAt(3) // returns NaN

ArrayBuffer

https://zh.javascript.info/arraybuffer-binary-arrays
ArrayBuffer 对象用来表示「通用的、固定长度的」原始二进制数据缓冲区。「ArrayBuffer 不能直接操作,而是要通过类型数组对象 或 DataView 对象来操作」,它们会将缓冲区中的数据表示为特定的格式,并通过这些格式来读写缓冲区的内容。

ArrayBuffer 简单说是一片内存,但是你不能直接用它。这就好比你在 C 里面,malloc 一片内存出来,你也会把它转换成 unsigned_int32 或者 int16 这些你需要的实际类型的数组/指针来用。 这就是 JS 里的 TypedArray 的作用,那些 Uint32Array 也好,Int16Array 也好,都是给 ArrayBuffer 提供了一个 “View”,MDN 上的原话叫做 “Multiple views on the same data”,对它们进行下标读写,最终都会反应到它所建立在的 ArrayBuffer 之上。 来源:https://www.zhihu.com/question/30401979

  1. const buffer = new ArrayBuffer(32); // 创建了一块 32 字节的内存区域
  2. // 可以使用buffer.byteLength来查看其长度。

如要操作 ArrayBuffer,我们需要使用“视图”对象。
视图对象本身并不存储任何东西。它是一副“眼镜”,透过它来解释存储在 ArrayBuffer 中的字节。
例如:

  • Uint8Array —— 将 ArrayBuffer 中的每个字节视为 0 到 255 之间的单个数字(每个字节是 8 位,因此只能容纳那么多)。这称为 “8 位无符号整数”。
  • Uint16Array —— 将每 2 个字节视为一个 0 到 65535 之间的整数。这称为 “16 位无符号整数”。
  • Uint32Array —— 将每 4 个字节视为一个 0 到 4294967295 之间的整数。这称为 “32 位无符号整数”。
  • Float64Array —— 将每 8 个字节视为一个 5.0x10-324 到 1.8x10308 之间的浮点数。

一个 16 字节 ArrayBuffer 中的二进制数据可以解释为 16 个“小数字”,或 8 个更大的数字(每个数字 2 个字节),或 4 个更大的数字(每个数字 4 个字节),或 2 个高精度的浮点数(每个数字 8 个字节)。
image.png

  1. let buffer = new ArrayBuffer(16); // 创建一个长度为 16 的 buffer
  2. let view = new Uint32Array(buffer); // 将 buffer 视为一个 32 位整数的序列,没4个字节一个整数
  3. alert(Uint32Array.BYTES_PER_ELEMENT); // 每个整数 4 个字节
  4. alert(view.length); // 4,它存储了 4 个整数
  5. alert(view.byteLength); // 16,字节中的大小
  6. // 让我们写入一个值
  7. view[0] = 123456;
  8. // 遍历值
  9. for(let num of view) {
  10. alert(num); // 123456,然后 0,0,0(一共 4 个值)
  11. }

Blob

使用

Blob:二进制文件类型

blob 表示二进制大对象(binary larget object),是 JavaScript 对不可修改二进制数据的封装类型。包含字符串的数组、ArrayBuffers、ArrayBufferViews,甚至其他 Blob 都可以用来创建 blob。

使用方法new Blob(array [, options])

  1. var htmlFragment = ['<a id="a"><b id="b">hey!</b></a>'];
  2. var myBlob = new Blob(htmlFragment, {type : 'text/html'});
  3. var obj = { hello: 'world' };
  4. var blob = new Blob([ JSON.stringify(obj) ], {type : 'application/json'})

Blob具有两个实例属性size和type

  1. var htmlFragment = ['<a id="a"><b id="b">hey!</b></a>'];
  2. var myBlob = new Blob(htmlFragment, {type : 'text/html'});
  3. myBlob.size // 32
  4. myBlob.type // "text/html"

Blob具有一个实例方法slice,用来拷贝原来的数据,返回的也是一个Blob实例。

  1. myBlob.slice(start, end, contentType)

slice方法有三个参数,都是可选的。它们依次是起始的字节位置(默认为0)、结束的字节位置(默认为size属性的值,该位置本身将不包含在拷贝的数据之中)、新实例的数据类型(默认为空字符串)。

下载

  1. <a href="/images/myw3schoolimage.jpg" download="w3logo">

download只适用于同源 URL 尽管 HTTP URL 需要位于同一源中,但是可以使用 blob:URLdata:URL ,以方便用户下载使用 JavaScript 生成的内容。

AJAX 请求时,如果指定responseType属性为blob,下载下来的就是一个 Blob 对象。

  1. // 解决上面的跨域下载问题
  2. downloadFile(url, fileName) {
  3. const xhr = new XMLHttpRequest();
  4. xhr.open("GET", url);
  5. xhr.responseType = 'blob';
  6. xhr.send();
  7. xhr.onload = function(e) {
  8. const url = URL.createObjectURL(xhr.response)//将blob对象转成blob地址
  9. const a = document.createElement('a');
  10. a.href = url
  11. a.download = fileName;
  12. a.click()
  13. URL.revokeObjectURL(url);
  14. }
  15. }

createObjectURL

浏览器允许使用URL.createObjectURL()方法,针对 Blob 对象生成一个临时 URL,以便于某些 API 使用。这个 URL 以blob://开头,表明对应一个 Blob 对象,协议头后面是一个识别符,用来唯一对应内存里面的 Blob 对象。

  1. /* blob生成文件下载 */
  2. const str = "<div>hello</div>";
  3. // 包装后的文件类型不能直接修改
  4. const blob = new Blob([str], {
  5. type: "text/html",
  6. });
  7. const a = document.createElement("a");
  8. const url = URL.createObjectURL(blob);
  9. a.download = "index.html";
  10. a.href = URL.createObjectURL(blob);
  11. a.click();
  12. URL.revokeObjectURL(a.href); // 释放URL 对象

URL.revokeObjectURL()方法用来释放URL.createObjectURL()方法生成的 URL 实例。它的参数就是URL.createObjectURL()方法返回的 URL 字符串。

File

文件选择器返回一个 FileList 对象,该对象是一个类似数组的成员,每个成员都是一个 File 实例对象
File 对象代表一个文件,用来读写文件信息。它继承了 Blob 对象,或者说是一种特殊的 Blob 对象,所有可以使用 Blob 对象的场合都可以使用它。
FileList 主要出现在两个场合。

  • 文件控件节点()的files属性,返回一个 FileList 实例。
  • 拖拉一组文件时,目标区的DataTransfer.files属性,返回一个 FileList 实例。
    1. // HTML 代码如下
    2. // <input id="fileItem" type="file">
    3. var files = document.getElementById('fileItem').files;
    4. var file = document.getElementById('fileItem').files[0];
    5. files instanceof FileList // true
    6. file instanceof File // true

    multiple=”multiple” 可开启多选

构造函数

  1. new File(array, name [, options])
  2. var file = new File(
  3. ['foo'],
  4. 'foo.txt',
  5. {
  6. type: 'text/plain',
  7. }
  8. );

File()构造函数接受三个参数。

  • array:一个数组,成员可以是二进制对象或字符串,表示文件的内容。
  • name:字符串,表示文件名或文件路径。
  • options:配置对象,设置实例的属性。该参数可选。

第三个参数配置对象,可以设置两个属性。

  • type:字符串,表示实例对象的 MIME 类型,默认值为空字符串。
  • lastModified:时间戳,表示上次修改的时间,默认为Date.now()。


    实例属性和方法

  • File.lastModified:最后修改时间

  • File.name:文件名或文件路径
  • File.size:文件大小(单位字节)
  • File.type:文件的 MIME 类型

    1. var myFile = new File([], 'file.bin', {
    2. lastModified: new Date(2018, 1, 1),
    3. });
    4. myFile.lastModified // 1517414400000
    5. myFile.name // "file.bin"
    6. myFile.size // 0
    7. myFile.type // ""

    File 对象没有自己的实例方法,由于继承了 Blob 对象,因此可以使用 Blob 的实例方法slice()。

    FileReader

    FileReader 对象用于读取 File 对象或 Blob 对象所包含的文件内容。
    浏览器原生提供一个FileReader构造函数,用来生成 FileReader 实例。

    1. var reader = new FileReader();
  • FileReader.result:读取完成后的文件内容,有可能是字符串,也可能是一个 ArrayBuffer 实例。

  • FileReader.onload:load事件(读取操作完成)的监听函数,通常在这个函数里面使用result属性,拿到文件内容。

取得 Blob 对象以后,可以通过 FileReader 对象,读取 Blob 对象的内容,即文件内容。
FileReader 对象提供四个方法,处理 Blob 对象。Blob 对象作为参数传入这些方法,然后以指定的格式返回。

  • FileReader.readAsText():返回文本,需要指定文本编码,默认为 UTF-8。
  • FileReader.readAsArrayBuffer():返回 ArrayBuffer 对象。
  • FileReader.readAsDataURL():返回 Data URL。
  • FileReader.readAsBinaryString():返回原始的二进制字符串。

    1. <body>
    2. <input type="file" id="input" multiple="multiple" />
    3. <script>
    4. /* input上传图片预览 */
    5. document.getElementById("input").addEventListener("change", (e) => {
    6. const file = e.target.files[0];
    7. const reader = new FileReader();
    8. reader.readAsDataURL(file); // base64
    9. reader.onload = () => {
    10. console.log(reader.result);
    11. // 新建图片标签预览
    12. const img = document.createElement("img");
    13. img.src = reader.result;
    14. document.body.appendChild(img);
    15. };
    16. });
    17. </script>
    18. </body>

    使用createObjectURL

    1. file.addEventListener('change', (e) => {
    2. let file = e.target.files[0] // 二进制文件类型
    3. // 实现图片预览
    4. const img = document.createElement('img')
    5. let url = img.src = URL.createObjectURL(file)
    6. document.body.appendChild(img)
    7. // URL.revokeObjectURL(url)// 销毁临时链接
    8. })
    1. 渲染后
    2. <img src="blob:http://localhost:52330/32134adc-b81a-4771-ae91-a26a88c2344d">

    Buffer

  • 缓冲区Buffer是暂时存放输入输出数据的一段内存。

  • JS语言没有二进制数据类型,而在处理TCP和文件流的时候,必须要处理二进制数据。
  • NodeJS提供了一个Buffer对象来提供对二进制数据的操作
  • 是一个表示固定内存分配的全局对象,也就是说要放到缓存区中的字节数需要提前确定
  • Buffer好比由一个8位字节元素组成的数组,可以有效的在JavasScript中表示二进制数据

Buffer定义

buffer的三种声明方式,通过长度来声明(大小)

  • 通过长度定义buffer ```javascript // 创建一个长度为 5、且用 0 填充的 Buffer。 const buffer = Buffer.alloc(5) //字节为单位 console.log(buffer) //

// 创建一个长度为 10、且用 0x1 填充的 Buffer。 const buf2 = Buffer.alloc(10, 1);

// 创建一个长度为 10、且未初始化的 Buffer。 const buf3 = Buffer.allocUnsafe(10);

  1. - 通过数组定义buffer
  2. ```javascript
  3. // 创建一个包含 [0x1, 0x2, 0x3] 的 Buffer。
  4. const buf4 = Buffer.from([1, 2, 3]);
  • 字符串创建
    1. const bf2 = Buffer.form('汉字') // <Buffer e6 b1 89 e5 ad 97>

常用方法

  • fill
  • write方法
  • writeInt8
  • toString方法
  • slice方法
  • copy方法
  • concat方法
  • isBuffer
  • length

image.png
[1.3万字] 玩转前端二进制
理解JavaScript中各种二进制对象关系