前言
在 Web 开发中,当我们处理文件时(创建,上传,下载),经常会遇到二进制数据。另一个典型的应用场景是图像处理。
在 JavaScript 中有很多种二进制数据格式,比如ArrayBuffer,Uint8Array,DataView,Blob,File 等等,不过 JavaScript 中的二进制数据是以非标准方式实现的。
下面我们来了解下这些数据格式及相互转换。
本文涉及到File,Blob,TypedArray,data url(Base64),blob url等等。
File
首先,我们还是拿前文的例子来看,显示用户选择的图片。
我们创建一个页面。提供选择图片功能。
- <!DOCTYPE html>
- <html>
- <head>
- <title>test</title>
- </head>
- <body>
- <input type="file" id="fileInput" name="选择图片"/>
- <div class="wrap-image">
- <canvas id="canvas"></canvas>
- </div>
- <script type="text/javascript">
- </script>
- </body>
- </html>
选择图片后,需要将图片显示到canvas中,我们在上面的script标签中加入下面的代码:
- const fileInput = document.getElementById('fileInput')
- const canvas = document.getElementById('canvas')
- fileInput.addEventListener('change', (e) => {
- let img = new Image
- const file = e.target.files[0]
- img.src = URL.createObjectURL(file)
- img.onload = () => {
- canvas.width = img.width
- canvas.height = img.height
- const context = canvas.getContext('2d')
- context.drawImage(img, 0, 0)
- }
- }, false)
选择一张图片后,change事件中获取到选择的文件e.target.files[0]:
File 对象是特殊类型的 Blob,可以用在任意的 Blob 类型的 context 中。
比如 FileReader, URL.createObjectURL(), createImageBitmap(), 及 XMLHttpRequest.send() 都能处理 Blob 和 File。
File 接口也继承了 Blob 接口的属性。上图的Prototype展开可以看到继承自Blob:
上面是最常见的file获取方式————从<input type="file">中获取。
- new File(fileParts, fileName, [options])
- fileParts —— Blob/BufferSource/String 类型值的数组
- fileName —— 文件名字符串
- options —— 可选对象
FileReader
FileReader 的用途是从 Blob(因此也从 File)对象中读取数据。
它使用事件来传递数据,因为从磁盘读取数据可能比较费时间。
可以读取为3种格式:
比如将 Blob 读取为 base64:
- const reader = new FileReader()
- reader.readAsDataURL(file) // 将 Blob 读取为 base64
使用时选择哪一种,要看如何使用数据。
读取过程中有下列事件:
1、loadstart: 开始加载
2、progress: 在读取过程中出现
3、load: 读取完成,没有 error
4、abort: 调用了 abort()取消操作
5、error: 出现 error
6、loadend: 读取完成,无论成功还是失败
使用最广泛的是load和error,比如下面的例子:
- <input type="file" onchange="readFile(this)">
- <script>
- const readFile = (input) => {
- const file = input.files[0]
- const reader = new FileReader()
- reader.readAsText(file)
- reader.onload = () => {
- console.log(reader.result) // 结果
- }
- reader.onerror = () => {
- console.log(reader.error) // error
- }
- }
- </script>
不过大多数情况下,我们不需要读取Blob,通过网络发送一个File很容易,像 XMLHttpRequest 或 fetch 等 API 本身就接受 File 对象。或者用URL.createObjectURL(file) 创建一个短的 url,并将其赋给 或 。这样,文件便可以下载文件或者将其呈现为图像,作为 canvas 等的一部分。
Blob