本文已参与「新人创作礼」活动,一起开启掘金创作之路。
项目中经常涉及到文件的操作,每次都得百度,这次还是整体学习一下吧。
Base64
Base64 是一组相似的二进制到文本(binary-to-text)的编码规则,使得二进制数据在解释成 radix-64 的表现形式后能够用 ASCII 字符串的格式表示出来。这个词出自一种 MIME 数据传输编码
javascript 中:atob()
函数能够解码通过 base-64 编码的字符串数据。btoa()
能够从二进制数据”字符串“创建一个 base-64 编码的 ASCII 字符串。atob
btoa
均使用字符串,想使用 ArrayBuffer,请往后看。
Base64会增加编码尺寸
每一个 Base64 字符实际上代表6比特位。3字节(1字节是8比特)的字符串/二进制文件可以转换成4个Base64字符。这意味着 Base64 格式的字符串或文件的尺寸约是原始尺寸的133%,大约增加了33%。如果编码很少,增加的比例可能会更高。例如: 'a' 进行 Base64 编码后是 ”YQ==“,尺寸增加了300%。
Blob
表示一个不可变、原始数据的类文件对象。它的数据可以按文本或者二进制的格式进行读取,也可以转换成 ReadableStream 来用于数据操作。
Blob 表示的并不一定是 Javascript 的原生格式的数据。 File 接口基于Blob,继承了Blob的功能并将其扩展使其支持用户系统上的文件。
constructor
new Blob(blobParts, options)
blobParts
是 Blob | BufferSource | String 类型的数组
options
可选对象:
type
Blob 类型,通常是MIME
endings
是否转换换行符,使Blob对应于当前操作系统的换行符( \r\n 或 \n )。默认是“transparent”,啥也不做。也可是 "native" 转换。
属性
Blob.size
所包含数据的大小(字节)。
Blob.type
数据的 MIME 类型。类型未知,则该值为空字符串。
方法
Blob.slice([start [,end[, contentType]]])
截取数据,返回一个新的 Blob。
Blob.stream()
返回一个能读取 blob 内容的 ReadableStream
Blob.text()
返回一个 promise 且包含 blob 所有内容的 UTF-8 格式的 USVString
Blob.arrayBuffer()
返回一个 promise 且包含 blob 所有内容的二进制格式 ArrayBuffer
// 从 Blob 中提取数据:除了 text 和 arrayBuffer, 还有一种方法是使用 FileReader
var reader = new FileReader();
reader.addEventListener("loadend", function(){
// reader.result 包含被转化为类型数组 typed array 的 blob
})
reader.readAsArrayBuffer(blob);
// 另一种方法是使用 Response 对象
var text = await (new Response(blob)).text()
Blob 用作 URL
<!-- 下载文件 -->
<a download="hello.txt" href="#" id="link">下载</a>
<script>
let blob = new Blob(["hello world"], {type: "text/plain"})
link.href = URL.createObjectURL(blob) // 需要介意内存, 需要使用revoke撤销它
URL.revokeObjectURL(link.href) // 释放 Blob 占用的内存
</script>
Blob 转 Base64
URL.createObjectURL 的一个替代方法是将 Blob 转换为 base64 编码的字符串。Base64 安全“可读”。但是对大的Blob进行编码时,性能和内存会有损耗。
let link = document.createElement('a');
link.download = "hello.txt"
let blob = new Blob(['hello world'], {type: 'text/plain'})
let reader = new FileReader();
reader.readAsDataURL(blob); // blob 转换成 base64 并调用 onload
reader.onload = function(){
link.href = reader.result;
link.click()
}
Img 转 Blob
let img = document.querySelector('img');
let canvas = document.createElement('canvas');
canvas.width = img.clientWidth;
canvas.heigth = img.clientHeight;
let context = canvas.getContext('2d');
context.drawImage(img, 0, 0);
canvas.toBlob(function(blob){
let link = doucment.createElement('a');
link.download = 'example.png';
link.href = URL.createObjectURL(blob);
link.click()
URL.revokeObjectURL(link.href)
}, 'image/png')
Blob 转 ArrayBuffer
const bufferPromise = await blob.arrayBuffer()
blob.arrayBuffer().then(buffer => /* 处理 ArrayBuffer */)
Blob 转 Stream
当我们需要处理大型blob时,将其转换成 stream 是非常有用的。
const readableStream = blob.stream();
const stream = readableStream.getReader();
while(true){
let { done, value } = await stream.read();
if (done) {
break
}
console.log(value);
}
File
File 对象是特殊类型的 Blob,可以用在任意的 Blob 类型的 context 中。比如说:FileReader | URL.createObjectURL | createImageBitmap() | XMLHttpRequest.send() 都能处理 Blob 和 File
constructor
new File(bits, name[, options])
bits
包含 ArrayBuffer | ArrayBufferView | Blob | DOMString 对象的 Array 或者这些对象的组合。这是 UTF-8 编码的文件内容
name
USVString,表示文件名称或文件路径。
options
选项对象,包含文件的可选属性。可用的选项如下:
type
: DOMString,表示文件的 MIME 类型,默认是 ”“。
lastModified
数值( 时间戳),默认是 Date.now()。
属性
lastModified
lastModifiedDate
name
size
webkitRelativePath
type
MIME type
方法
没有定义任何方法,从 Blob 继承了 slice 方法
FileReader 🥝
FileReader 是一个对象,其唯一目的是从 Blob(因此也能从 File) 对象中读取数据。它用事件来传递数据,因为从磁盘中读取数据可能比较费时间。
constructor
new FileReader()
没有参数
方法
readAsArrayBuffer(blob)
将数据读取为二进制格式的 ArrayBuffer 。用于二进制文件,执行低级别的二进制操作。比如:切片(slice)之类的高级别的操作。
readAsText(blob, [encoding])
将数据读取为给定编码(default:UTF-8)的文本字符串。用于文本文件,当我们想获取字符串的时候。
readAsDataURL(blob)
读取二进制数据,并将其编码成 base64 的 data url。用于想在src中使用此数据。
abort()
取消操作。
读取中有以下事件:
loadstart
开始加载
progress
读取中
load
读取完成,没有error
abort
调用了 abort()
error
出现 error
loadend
读取完成,不管成功还是失败
读取完成后,可以用以下方式获取结果:
reader.result
reader.error
// <input onchange="readFile(this)"/>
function readFile(input) {
let file = input.files[0];
let reader = new FileReader();
reader.readAsText(file);
reader.onload = function () {
console.log(reader.result)
}
reader.onerror = function () {
console.log(reader.error)
}
}