Blob and File

有趣的 Blob 和 File API

现代 Web 实现了 File 和 Blob 两个接口, 前者允许 JavaScript 在用户授权的情况下读取特定的文件, 后者则赋予 JavaScript 创建文件资源的能力. Photopea.com 作为一个网页端的 Photoshop 可以快速打开几百 MB 的 PSD 文件, 并且随时可以保存为新的 PSD 文件下载下来, 也是因为这两者的应用. 我先前做了 ook.dev/tools/long-screen 这个工具来拼接视频截图为单张长图, 在读取文件和生成可下载的图片时也用到了这两个 API.

Blob

Blob 对象表示一个不可变, 原始数据的类文件对象. Blob 表示的不一定是 JavaScript 原生格式的数据. File 接口基于Blob, 继承了 blob 的功能并将其扩展使其支持用户系统上的文件.

Blob - Web API 接口参考 | MDN

// 创建一个 blob 对象, blobParts 为一个数组. MIME_TYPE 为 blobParts 对应的类型.
const blob = new Blob(blobParts, { type: MIME_TYPE })

// 为该 blob 对象创建可用的 URL
const url = URL.createObjectURL(blob)

这个 URL 可以跨 Tab 使用, 所以如果创建了一个新的 HTML 文件, 倒是可以直接用 window.open 开启一个新的 tab 用作预览. 不过有看到反馈说无法直接 window.open 整个 objectURL, 但是可以在打开新的 tab 之后, push 得到的 URL 过去.

File

文件(File)接口提供有关文件的信息,并允许网页中的 JavaScript 访问其内容。

通常情况下, File 对象是来自用户在一个 <input> 元素上选择文件后返回的 FileList 对象, 也可以是来自由拖放操作生成的 DataTransfer 对象,或者来自 HTMLCanvasElement 上的 mozGetAsFile() API。

File 对象是特殊类型的 Blob, 且可以用在任意的 Blob 类型的 context 中. 比如说, FileReader, URL.createObjectURL(), createImageBitmap(), 及 XMLHttpRequest.send() 都能处理 Blob 和 File.

File - Web API 接口参考 | MDN

File 在 Blob 的基础上多了一些属性. 读取 File 与读取 Blob 一样, 需要 FileReader.

const reader = new FileReader()
reader.addEventListener("loadend", function() {
    // reader.result
})

reader.readAsDataURL() // .readAsText(), .readAsBinaryString(), .readAsArrayBuffer()

Usage

那么如果结合这两者做一些小工具, 比如转换一下字幕文件格式. 那么流程上就是:

  1. 通过拖拽上传或者 input 选择文件, 获取到 FileList / File 对象.
  2. 通过 FileReader 完成文件内容的读取
  3. 对文件内容进行处理, 生成需要的内容
  4. 创建 blob 对象, 指定 MIME Type
  5. 使用 URL.createObjectURL() 为 blob 对象创建 URL
  6. 将下载入口展示给用户

然后就好了, 对于一些比较轻量的工作, 就比如要把 .srt 转成 .vtt, 一个 HTML 文件就可以完成, 不占空间, 不依赖网络, 没有任何副作用. 期待更多强大的 API 被实现, 比如 目前处于草案阶段的 FileSystemDirectoryReader.