JS各种数据流之间的格式(ArrayBuffer、Uint8Array、Blob、 File、DataURL)相互转换及应用
前端网页 File 上传、下载,Canvas 保存图片,Ajax 和 Fetch 二进制流传输,PDF 预览,浏览器上 WebAssembly 的应用 等等都需要到 ArrayBuffer 和 Blob 。
API介绍
FileReader
对象允许Web应用程序异步读取存储在用户计算机上的文件(或原始数据缓冲区)的内容,使用 File 或 Blob 对象指定要读取的文件或数据。Blob
对象表示一个不可变、原始数据的类文件对象。它的数据可以按文本或二进制的格式进行读取,也可以转换成 ReadableStream 来用于数据操作。Blob 表示的不一定是 JavaScript 原生格式的数据。File 接口基于 Blob,继承了 blob 的功能并将其扩展使其支持用户系统上的文件。
属性名称 | 读/写 | 描述 |
---|---|---|
size | 只读 | Blob 对象中所包含数据的大小(字节)。 |
type | 只读 | 一个字符串,表明该Blob对象所包含数据的MIME类型。如果类型未知,则该值为空字符串。例如 “image/png”. |
ArrayBuffer
对象代表储存二进制数据的一段内存,它不能直接读写,只能通过视图(TypedArray 视图和 DataView 视图)来读写,视图的作用是以指定格式解读二进制数据。Uint8Array
对象是 ArrayBuffer 的一个数据类型(8 位不带符号整数)。TextEncoder
接受代码点流作为输入,并提供 UTF-8 字节流作为输出。TextDecoder
接口表示一个文本解码器,一个解码器只支持一种特定文本编码,例如 utf-8、iso-8859-2、koi8、cp1261,gbk 等等。解码器将字节流作为输入,并提供代码点流作为输出。base64
Base64是网络上最常见的用于传输8Bit字节码的编码方式之一,Base64就是一种基于64个可打印字符来表示二进制数据的方法。编码规则:把3个字节变成4个字节;每76个字符加一个换行符;最后的结束符也要处理。
注意: 二进制数组并不是真正的
js各种数据流之间的格式转换数组,而是类似数组的对象。
字符与ArrayBuffer,Uint8Array相互转换
1、TextEncoder => ArrayBuffer
let encoder = new TextEncoder(); // 字符 转 Uint8Array let uint8Array = encoder.encode("你好啊"); // Uint8Array 转 ArrayBuffer let arrayBuffer = uint8Array.buffer
复制
2、Blob => ArrayBuffer
let str = 'hello,你好吗?' let blob = new Blob([str],{type:'text/plain;charset=utf-8'}); let utf8decoder = new TextDecoder() blob.arrayBuffer().then(buffer=>{ // ArrayBuffer console.log(buffer) let text = utf8decoder.decode(buffer) // String console.log(text) })
复制
3.FileReader => ArrayBuffer
let str = 'hello,你好吗?' let blob = new Blob([str],{type:'text/plain;charset=utf-8'}); let utf8decoder = new TextDecoder() let fr = new FileReader() fr.readAsArrayBuffer(blob) fr.onload = function(res) { // ArrayBuffer let buffer = fr.result console.log(buffer) let text = utf8decoder.decode(buffer) // String console.log(text) }
复制
转换及应用
1.将file转换成DataURL,实现本地图片上传预览
<input type="file" id="file"> <img id="img">
复制
- 利用URL.createObjectURL()
let img = document.getElementById('img') let file = document.getElementById('file') file.onchange = function () { let imgFile = this.files[0] img.src = URL.createObjectURL(imgFile) img.onload = function () { URL.revokeObjectURL(this.src) } }
复制
- 利用FileReader.readAsDataURL()
let img = document.getElementById('img') let file = document.getElementById('file') file.onchange = function (e) { let imgFile = this.files[0] let fileReader = new FileReader() fileReader.readAsDataURL(imgFile) fileReader.onload = function () { img.src = this.result } }
复制
2、将DataURL转成file
function dataURLToFile (dataUrl, fileName) { const dataArr = dataUrl.split(',') const mime = dataArr[0].match(/:(.*);/)[1] const originStr = atob(dataArr[1]) return new File([originStr], fileName, { type: mime }) } dataURLToFile('data:text/plain;base64,YWFhYWFhYQ==', '测试文件') // File {name: '测试文件', lastModified: 1640784525620, lastModifiedDate: Wed Dec 29 2021 21:28:45 GMT+0800 (中国标准时间), webkitRelativePath: '', size: 7, …}
复制
3.将canvas转成DataURL,实现将canvans变成图片,或生成指定格式的图片,实现图片格式的转换
// html <input type="file" accept="image/*" id="file"> // js document.querySelector('#file').onchange = function () { canvasToDataURL(this.files[0]) .then(res => console.log(res)) } function canvasToDataURL (file) { return new Promise(resolve => { const img = document.createElement('img') img.src = URL.createObjectURL(file) img.onload = function () { const canvas = document.createElement('canvas') canvas.width = img.width canvas.height = img.height const ctx = canvas.getContext('2d') ctx.drawImage(img, 0, 0) resolve(canvas.toDataURL('image/png', 1)) } }) }
复制
这个方法返回的是图片base64,用来生成图片的,默认png格式,也可以通过传递参数改变图片格式,还能改变图片保存的质量。
如:canvas.toDataURL(“images/jpeg”,0) ,第一个参数就是把图片编码为jpeg格式,第二个参数(0-1)就是指定图片质量,数值越大质量越高,不过对于image/png格式没法设置图片质量。
另外,chrome还支持自家的image/webp格式图片,也能设置图片质量, 实现图片压缩。
4.将DataURL转成canvas
function dataUrlToCanvas (dataUrl) { return new Promise(resolve => { const img = new Image() img.src = dataUrl img.onload = function () { const canvas = document.createElement('canvas') canvas.width = this.width canvas.height = this.height const ctx = canvas.getContext('2d') ctx.drawImage(this, 0, 0) resolve(canvas) } }) } const dataUrl = 'data:image/png;base64,iVBORw0KGgoAAAANSUh...' dataUrlToCanvas(dataUrl) .then(res => document.body.appendChild(res)
复制
5.将canvas转成file
1.将canvas转成blob
利用canvas.toBlob()
// html <input type="file" accept="image/*" id="file"> // js document.querySelector('#file').onchange = function () { canvasToDataURL(this.files[0]) .then(res => console.log(res)) } function canvasToDataURL (file) { return new Promise(resolve => { const img = document.createElement('img') img.src = URL.createObjectURL(file) img.onload = function () { const canvas = document.createElement('canvas') canvas.width = img.width canvas.height = img.height const ctx = canvas.getContext('2d') ctx.drawImage(img, 0, 0) canvas.toBlob(function (e) { resolve(e) }, 'image/png', 1) } }) }
复制
2.将blob转成file
利用new File();
function blobToFile(blob, filename, type) { return new File([blob], filename, { type }) } blobToFile('test info', 'test', 'text/plain' )
复制