文件下载方式
1.a标签
要求资源是同源的,支持跨域下载看下文的Blob
<a href='下载文件的url' download>点我下载</a>
2.window.open
会有一个打开tab页的过程,浏览器可以直接解析的会直接显示出来,不能解析的会下载
window.open('目标url')
引申:
window.open("webpage.htm", "_self");
window.location.href = "webpage.htm";
都是在当前页面打开url
// window.location.href 是一个属性,它会告诉你浏览器的当前URL位置。更改属性的值将重定向页面。
// window.open()是一种方法,您可以将 URL 传递给要在新窗口中打开的 URL。
Data URI
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=
【4】第④部分 [;
【5】第⑤部分 ,
Base64
Base64: 将数据用64个字符进行编码的方式,只要数据为二进制的都可以被编码,适用于文本,图片等。 原理:3×8 = 4×6 。 将原来每8bit,即一字节的,拆分成4个6bit的,再填0变成8bit,所以相当于 每3位变成了4位,增加了1/3的尺寸。 作用:编完码后,文本,图片都变成了流stream的感觉,可以用于传输
<img width="40" height="30" src="data:image/jpg;base64,/9j/4QMZRXhpZgAASUkqAAgAAAAL...." />
atob
base64 转 字符串btoa
base64编码window.atob('RnJ1aXQgQnJv');
// 返回:'Fruit Bro
base64转换为文件
Uint8Array 数组类型表示一个8位无符号整型数组,创建时内容被初始化为0。创建完后,可以以对象的方式或使用数组下标索引的方式引用数组中的元素。export function dataURLtoFile(dataurl, filename) {
const arr = dataurl.split(',');
const mime = arr[0].match(/:(.*?);/)[1];
const bstr = atob(arr[1]);
let n = bstr.length;
const u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new File([u8arr], filename, { type: mime });
}
charCodeAt() 方法返回 0 到 65535 之间的整数,表示给定索引处的 UTF-16 代码单元。
不同索引情况下返回的 Unicode 值:
"ABC".charCodeAt(0) // returns 65:"A"
"ABC".charCodeAt(1) // returns 66:"B"
"ABC".charCodeAt(2) // returns 67:"C"
"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
const buffer = new ArrayBuffer(32); // 创建了一块 32 字节的内存区域
// 可以使用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 个字节)。
、
let buffer = new ArrayBuffer(16); // 创建一个长度为 16 的 buffer
let view = new Uint32Array(buffer); // 将 buffer 视为一个 32 位整数的序列,没4个字节一个整数
alert(Uint32Array.BYTES_PER_ELEMENT); // 每个整数 4 个字节
alert(view.length); // 4,它存储了 4 个整数
alert(view.byteLength); // 16,字节中的大小
// 让我们写入一个值
view[0] = 123456;
// 遍历值
for(let num of view) {
alert(num); // 123456,然后 0,0,0(一共 4 个值)
}
Blob
使用
Blob:二进制文件类型
blob 表示二进制大对象(binary larget object),是 JavaScript 对不可修改二进制数据的封装类型。包含字符串的数组、ArrayBuffers、ArrayBufferViews,甚至其他 Blob 都可以用来创建 blob。
使用方法new Blob(array [, options])
var htmlFragment = ['<a id="a"><b id="b">hey!</b></a>'];
var myBlob = new Blob(htmlFragment, {type : 'text/html'});
var obj = { hello: 'world' };
var blob = new Blob([ JSON.stringify(obj) ], {type : 'application/json'})
Blob具有两个实例属性size和type
var htmlFragment = ['<a id="a"><b id="b">hey!</b></a>'];
var myBlob = new Blob(htmlFragment, {type : 'text/html'});
myBlob.size // 32
myBlob.type // "text/html"
Blob具有一个实例方法slice,用来拷贝原来的数据,返回的也是一个Blob实例。
myBlob.slice(start, end, contentType)
slice方法有三个参数,都是可选的。它们依次是起始的字节位置(默认为0)、结束的字节位置(默认为size属性的值,该位置本身将不包含在拷贝的数据之中)、新实例的数据类型(默认为空字符串)。
下载
download只适用于同源 URL 尽管 HTTP URL 需要位于同一源中,但是可以使用 blob:URL 和 data:URL ,以方便用户下载使用 JavaScript 生成的内容。
AJAX 请求时,如果指定responseType属性为blob,下载下来的就是一个 Blob 对象。
// 解决上面的跨域下载问题
downloadFile(url, fileName) {
const xhr = new XMLHttpRequest();
xhr.open("GET", url);
xhr.responseType = 'blob';
xhr.send();
xhr.onload = function(e) {
const url = URL.createObjectURL(xhr.response)//将blob对象转成blob地址
const a = document.createElement('a');
a.href = url
a.download = fileName;
a.click()
URL.revokeObjectURL(url);
}
}
createObjectURL
浏览器允许使用URL.createObjectURL()方法,针对 Blob 对象生成一个临时 URL,以便于某些 API 使用。这个 URL 以blob://开头,表明对应一个 Blob 对象,协议头后面是一个识别符,用来唯一对应内存里面的 Blob 对象。
/* blob生成文件下载 */
const str = "<div>hello</div>";
// 包装后的文件类型不能直接修改
const blob = new Blob([str], {
type: "text/html",
});
const a = document.createElement("a");
const url = URL.createObjectURL(blob);
a.download = "index.html";
a.href = URL.createObjectURL(blob);
a.click();
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 实例。
// HTML 代码如下
// <input id="fileItem" type="file">
var files = document.getElementById('fileItem').files;
var file = document.getElementById('fileItem').files[0];
files instanceof FileList // true
file instanceof File // true
multiple=”multiple” 可开启多选
构造函数
new File(array, name [, options])
var file = new File(
['foo'],
'foo.txt',
{
type: 'text/plain',
}
);
File()构造函数接受三个参数。
- array:一个数组,成员可以是二进制对象或字符串,表示文件的内容。
- name:字符串,表示文件名或文件路径。
- options:配置对象,设置实例的属性。该参数可选。
第三个参数配置对象,可以设置两个属性。
- type:字符串,表示实例对象的 MIME 类型,默认值为空字符串。
lastModified:时间戳,表示上次修改的时间,默认为Date.now()。
实例属性和方法
File.lastModified:最后修改时间
- File.name:文件名或文件路径
- File.size:文件大小(单位字节)
File.type:文件的 MIME 类型
var myFile = new File([], 'file.bin', {
lastModified: new Date(2018, 1, 1),
});
myFile.lastModified // 1517414400000
myFile.name // "file.bin"
myFile.size // 0
myFile.type // ""
File 对象没有自己的实例方法,由于继承了 Blob 对象,因此可以使用 Blob 的实例方法slice()。
FileReader
FileReader 对象用于读取 File 对象或 Blob 对象所包含的文件内容。
浏览器原生提供一个FileReader构造函数,用来生成 FileReader 实例。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():返回原始的二进制字符串。
<body>
<input type="file" id="input" multiple="multiple" />
<script>
/* input上传图片预览 */
document.getElementById("input").addEventListener("change", (e) => {
const file = e.target.files[0];
const reader = new FileReader();
reader.readAsDataURL(file); // base64
reader.onload = () => {
console.log(reader.result);
// 新建图片标签预览
const img = document.createElement("img");
img.src = reader.result;
document.body.appendChild(img);
};
});
</script>
</body>
使用createObjectURL
file.addEventListener('change', (e) => {
let file = e.target.files[0] // 二进制文件类型
// 实现图片预览
const img = document.createElement('img')
let url = img.src = URL.createObjectURL(file)
document.body.appendChild(img)
// URL.revokeObjectURL(url)// 销毁临时链接
})
渲染后
<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);
- 通过数组定义buffer
```javascript
// 创建一个包含 [0x1, 0x2, 0x3] 的 Buffer。
const buf4 = Buffer.from([1, 2, 3]);
- 字符串创建
const bf2 = Buffer.form('汉字') // <Buffer e6 b1 89 e5 ad 97>
常用方法
- fill
- write方法
- writeInt8
- toString方法
- slice方法
- copy方法
- concat方法
- isBuffer
- length