File API

W3C 工作草案

关于此文档的更多细节
此版本
https://w3org.cn/TR/2025/WD-FileAPI-20251203/
最新发布版本
https://w3org.cn/TR/FileAPI/
编辑草案
https://w3c.github.io/FileAPI/
历史版本
历史
https://w3org.cn/standards/history/FileAPI/
反馈
GitHub
文档内联
编辑
(Google)
前任编辑
Arun Ranganathan (Mozilla Corporation)
测试
web-platform-tests FileAPI/ (正在进行的工作)

摘要

本规范提供了一个用于在 Web 应用中表示文件对象的 API,以及用于以编程方式选择这些对象并访问其数据的 API。这包括:

此外,本规范还定义了用于线程化 Web 应用中同步读取文件的对象。

§ 10 需求与用例 涵盖了本规范背后的动机。

此 API 旨在与 Web 平台上的其他 API 和元素结合使用,特别是:XMLHttpRequest(例如使用重载的 send() 方法处理 FileBlob 参数)、postMessage()DataTransfer[HTML] 中定义的拖放 API 的一部分)以及 Web Workers。此外,当 input 元素处于 File Upload(文件上传)状态 [HTML] 时,应能够以编程方式从该元素获取文件列表。这些行为在相应的附属规范中定义。

关于本文档

本节描述了本文件发布时的状态。当前的 W3C 出版物列表和本技术报告的最新版本可以在 W3C 标准和草案索引中找到。

本文档由 Web 应用工作组 作为工作草案,通过 推荐标准轨道 (Recommendation track) 发布。发布为工作草案并不意味着得到 W3C 及其成员的认可。

这是一个草案文档,可能随时会被其他文档更新、替换或废弃。将其作为进展中的工作之外的任何内容进行引用是不恰当的。

此前对本规范的讨论已在其他两个邮件列表中进行:public-webapps@w3.org (归档) 和 public-webapi@w3.org (归档)。正在进行的讨论将在 public-webapps@w3.org 邮件列表中进行。

本草案包含对之前“最后通牒工作草案”(Last Call Working Draft)所做的更改。请按照上述说明将意见发送至 public-webapi@w3.org。您可以在 W3C Wiki 上查看“最后通牒反馈”:https://w3org.cn/wiki/Webapps/LCWD-FileAPI-20130912

一份实现报告是从测试套件中自动生成的。

本文档由在 W3C 专利政策 下运作的小组编写。W3C 维护了一份 与该小组交付成果相关的专利披露公开列表;该页面还包括披露专利的指南。任何对个人认为包含 必要权利要求 的专利拥有实际知识的个人,必须根据 W3C 专利政策第 6 节 披露该信息。

本文件受 2025 年 8 月 18 日 W3C 流程文件的管辖。

1. 引言

本节是资料性的。

Web 应用应具备处理尽可能广泛的用户输入的能力,包括用户希望上传到远程服务器或在丰富的 Web 应用中操作的文件。本规范定义了文件的基本表示形式、文件列表、因访问文件而引发的错误,以及读取文件的编程方式。此外,本规范还定义了一个接口,用于表示可以在符合要求的用户代理的主线程上异步处理的“原始数据”。本规范中定义的接口和 API 可以与暴露给 Web 平台的其他接口和 API 一起使用。

File 接口表示通常从底层文件系统获取的文件数据,而 Blob 接口(“二进制大对象”——一个最初在 Google Gears 中引入到 Web API 的名称)表示不可变的原始数据。FileBlob 读取应在主线程上异步进行,并在线程化的 Web 应用中使用可选的同步 API。用于读取文件的异步 API 可以防止阻塞用户代理的主线程并导致 UI“冻结”。本规范定义了一个基于 *事件模型* 的异步 API,用于读取和访问 FileBlob 的数据。FileReader 对象提供异步读取方法,通过事件处理器内容属性和触发事件来访问该文件的数据。事件和事件处理器的使用允许独立的代码块监控 *读取进度*(这对远程驱动器或挂载驱动器特别有用,因为这些驱动器的文件访问性能可能与本地驱动器不同)以及在读取文件过程中可能出现的错误状况。一个示例将有助于说明。

在下面的示例中,不同的代码块处理进度、错误和成功条件。
function startRead() {
  // obtain input element through DOM

  var file = document.getElementById('file').files[0];
  if(file){
    getAsText(file);
  }
}

function getAsText(readFile) {

  var reader = new FileReader();

  // Read file into memory as UTF-16
  reader.readAsText(readFile, "UTF-16");

  // Handle progress, success, and errors
  reader.onprogress = updateProgress;
  reader.onload = loaded;
  reader.onerror = errorHandler;
}

function updateProgress(evt) {
  if (evt.lengthComputable) {
    // evt.loaded and evt.total are ProgressEvent properties
    var loaded = (evt.loaded / evt.total);
    if (loaded < 1) {
      // Increase the prog bar length
      // style.width = (loaded * 200) + "px";
    }
  }
}

function loaded(evt) {
  // Obtain the read file data
  var fileString = evt.target.result;
  // Handle UTF-16 file dump
  if(utils.regexp.isChinese(fileString)) {
    //Chinese Characters + Name validation
  }
  else {
    // run other charset test
  }
  // xhr.send(fileString)
}

function errorHandler(evt) {
  if(evt.target.error.name == "NotReadableError") {
    // The file could not be read
  }
}

2. 术语与算法

当本规范提到终止算法时,用户代理必须在完成当前步骤后终止该算法。本规范中定义的异步 读取方法 可能会在该算法终止之前返回,并可以通过 abort() 调用来终止。

本规范中的算法和步骤使用以下数学运算

术语 Unix 纪元(Unix Epoch) 在本规范中用于指代 1970 年 1 月 1 日 00:00:00 UTC(或 1970-01-01T00:00:00Z ISO 8601)的时间;这与 ECMA-262 [ECMA-262] 中概念上的“0”时间相同。

切片 blob(slice blob) 算法在给定 Blob blobstartendcontentType 时,用于指代以下步骤,并返回一个新的 Blob,其中包含从 start 参数范围到但不包括 end 参数的字节。它必须按如下方式执行
  1. originalSizeblobsize

  2. start 参数(如果非空)是 切片 blob 调用的起始点值,并且必须被视为字节顺序位置,第 0 位表示第一个字节。用户代理必须根据以下规则标准化 start

    1. 如果 start 为空,令 relativeStart 为 0。
    2. 如果 start 为负数,令 relativeStartmax((originalSize + start), 0)
    3. 否则,令 relativeStartmin(start, originalSize)
  3. end 参数(如果非空)是 切片 blob 调用的结束点值。用户代理必须根据以下规则标准化 end

    1. 如果 end 为空,令 relativeEndoriginalSize
    2. 如果 end 为负数,令 relativeEndmax((originalSize + end), 0)
    3. 否则,令 relativeEndmin(end, originalSize)
  4. contentType 参数(如果非空)用于设置以 ASCII 编码的小写字符串,表示 Blob 的媒体类型。用户代理必须根据以下规则标准化 contentType

    1. 如果 contentType 为空,令 relativeContentType 设置为空字符串。
    2. 否则,令 relativeContentType 设置为 contentType 并运行以下子步骤
      1. 如果 relativeContentType 包含 U+0020 到 U+007E 范围之外的任何字符,则将 relativeContentType 设置为空字符串并从这些子步骤返回。

      2. relativeContentType 中的每个字符转换为 ASCII 小写

  5. spanmax((relativeEnd - relativeStart), 0)

  6. 返回一个具有以下特征的新 Blob 对象 S

    1. S 指代从 blob 关联的 字节 序列中获取的 span 个连续 字节,起始于字节顺序位置 relativeStart字节
    2. S.size = span
    3. S.type = relativeContentType

3. Blob 接口与二进制数据

Blob 对象指代一个 字节 序列,并具有一个 size 属性(它是字节序列中的总字节数)和一个 type 属性(它是以 ASCII 编码的小写字符串,表示 字节 序列的媒体类型)。

每个 Blob 必须具有一个内部的 快照状态(snapshot state),如果存在任何此类底层存储,它必须初始设置为底层存储的状态。关于 快照状态 的进一步规范定义可以在 File 中找到。

[Exposed=(Window,Worker), Serializable]
interface Blob {
  constructor(optional sequence<BlobPart> blobParts,
              optional BlobPropertyBag options = {});

  readonly attribute unsigned long long size;
  readonly attribute DOMString type;

  // slice Blob into byte-ranged chunks
  Blob slice(optional [Clamp] long long start,
            optional [Clamp] long long end,
            optional DOMString contentType);

  // read from the Blob.
  [NewObject] ReadableStream stream();
  [NewObject] Promise<USVString> text();
  [NewObject] Promise<ArrayBuffer> arrayBuffer();
  [NewObject] Promise<Uint8Array> bytes();
};

enum EndingType { "transparent", "native" };

dictionary BlobPropertyBag {
  DOMString type = "";
  EndingType endings = "transparent";
};

typedef (BufferSource or Blob or USVString) BlobPart;

Blob 对象是 可序列化对象。给定 valueserialized,其 序列化步骤 为:

  1. serialized.[[SnapshotState]] 设置为 value快照状态

  2. serialized.[[ByteSequence]] 设置为 value 的底层字节序列。

给定 serializedvalue,其 反序列化步骤 为:

  1. value快照状态 设置为 serialized.[[SnapshotState]]。

  2. value 的底层字节序列设置为 serialized.[[ByteSequence]]。

Blob blob 具有一个关联的 获取流(get stream) 算法,该算法执行以下步骤:
  1. stream 为在 blob相关 Realm 中创建的 ReadableStream

  2. 设置 具有字节读取支持的 stream

  3. 并行运行以下步骤

    1. 当并非 blob 的所有字节都已读取时:

      1. bytes 为从 blob 中读取 数据块(chunk) 时产生的 字节序列;如果无法读取数据块,则为失败。

      2. 在全局任务队列中排队 文件读取任务源 的任务,给定 blob相关全局对象,以执行以下步骤:

        1. 如果 bytes 为失败,则以 失败原因 报错(error) stream 并中止这些步骤。

        2. chunk 为包装了包含 bytesArrayBuffer 的新 Uint8Array。如果创建 ArrayBuffer 抛出异常,则以该异常 报错 stream 并中止这些步骤。

        3. chunk 加入队列(Enqueue)stream 中。

      我们需要更具体地说明从 Blob 读取的实际操作、可能发生的错误,也许还有关于数据块大小的内容等。

  4. 返回 stream

3.1. 构造函数

Blob() 构造函数可以使用零个或多个参数调用。当调用 Blob() 构造函数时,用户代理必须运行以下步骤:
  1. 如果以零个参数调用,则返回一个新的 Blob 对象,该对象由 0 字节组成,size 设置为 0,且 type 设置为空字符串。

  2. bytes 为给定 blobPartsoptions 处理 blob 部分(processing blob parts) 的结果。

  3. 如果 options 参数的 type 成员不是空字符串,则运行以下子步骤:

    1. ttype 字典成员。如果 t 包含 U+0020 到 U+007E 范围之外的任何字符,则将 t 设置为空字符串并从这些子步骤返回。

    2. t 中的每个字符转换为 ASCII 小写

  4. 返回一个 Blob 对象,该对象将其关联的 字节 序列指代为 bytes,其 size 设置为 bytes 的长度,其 type 设置为上述子步骤中的 t 的值。

3.1.1. 构造函数参数

Blob() 构造函数可以使用以下参数调用:

一个 blobParts 序列(sequence)
它接受任意数量的以下类型的元素,并且顺序不限:
一个 可选的 BlobPropertyBag
它接受这些可选成员:
处理 blob 部分(process blob parts),给定一系列 BlobPartpartsBlobPropertyBag options,运行以下步骤:
  1. bytes 为空字节序列。

  2. 对于 parts 中的每个 element

    1. 如果 elementUSVString,运行以下子步骤:

      1. selement

      2. 如果 optionsendings 成员为 "native",则将 s 设置为 element换行符转换为原生格式 的结果。

      3. s 进行 UTF-8 编码 的结果追加到 bytes

        注意:来自 WebIDL [WebIDL] 的算法会将无效 utf-16 字符串中不匹配的代理项替换为 U+FFFD 替换字符。在某些场景下,Blob 构造函数可能会因字符序列丢失或乱码而导致数据丢失。

    2. 如果 elementBufferSource,则 获取缓冲区源所持有的字节副本,并将这些字节追加到 bytes

    3. 如果 elementBlob,则将它表示的字节追加到 bytes

      注意:Blob 数组元素的 type 将被忽略,且不会影响返回的 Blob 对象的 type

  3. 返回 bytes

将换行符转换为原生格式(convert line endings to native),对于 字符串 s,运行以下步骤:
  1. native line ending码点 U+000A LF。

  2. 如果底层平台的约定是将换行符表示为回车和换行序列,则将 native line ending 设置为 码点 U+000D CR 后跟 码点 U+000A LF。

  3. result 设置为空 字符串

  4. positions位置变量,最初指向 s 的起始处。

  5. token收集s 中给定的 position 开始且不等于 U+000A LF 或 U+000D CR 的 码点序列 的结果。

  6. token 追加到 result

  7. position 未超过 s 的末尾时:

    1. 如果 sposition 处的 码点 等于 U+000D CR:

      1. native line ending 追加到 result

      2. position 前进 1。

      3. 如果 position 未超过 s 的末尾且 sposition 处的 码点 等于 U+000A LF,则将 position 前进 1。

    2. 否则,如果 sposition 处的 码点 等于 U+000A LF,则将 position 前进 1 并将 native line ending 追加到 result

    3. token收集s 中给定的 position 开始且不等于 U+000A LF 或 U+000D CR 的 码点序列 的结果。

    4. token 追加到 result

  8. 返回 result

以下是构造函数的使用示例。
// Create a new Blob object

var a = new Blob();

// Create a 1024-byte ArrayBuffer
// buffer could also come from reading a File

var buffer = new ArrayBuffer(1024);

// Create ArrayBufferView objects based on buffer

var shorts = new Uint16Array(buffer, 512, 128);
var bytes = new Uint8Array(buffer, shorts.byteOffset + shorts.byteLength);

var b = new Blob(["foobarbazetcetc" + "birdiebirdieboo"], {type: "text/plain;charset=utf-8"});

var c = new Blob([b, shorts]);

var a = new Blob([b, c, bytes]);

var d = new Blob([buffer, b, c, bytes]);

3.2. 属性

size 类型为 unsigned long long,只读
返回字节序列的大小(以字节为单位)。在获取时,符合要求的用户代理必须返回可由 FileReaderFileReaderSync 对象读取的总字节数;如果 Blob 没有可读取的字节,则返回 0。
type 类型为 DOMString,只读
以 ASCII 编码的小写字符串,表示 Blob 的媒体类型。在获取时,用户代理必须将 Blob 的类型作为 ASCII 编码的小写字符串返回,使得当其转换为 字节 序列时,它是一个 可解析的 MIME 类型;或者,如果类型无法确定,则返回空字符串(0 字节)。

type 属性可以由 Web 应用本身通过构造函数调用和 slice() 调用设置;在这些情况下,该属性的进一步规范条件分别在 § 3.1 构造函数§ 4.1 构造函数§ 3.3.1 slice() 方法 中。用户代理也可以确定 Blobtype,特别是如果 字节 序列来自磁盘文件;在这种情况下,进一步的规范条件在 文件类型指南 中。

注意:如果对从表示 Blob 对象类型的 ASCII 编码字符串转换而来的字节序列执行 解析 MIME 类型 算法不返回失败,则 Blob 的类型 t 被视为 可解析的 MIME 类型

注意:type 属性的使用会通知 包装数据(package data) 算法,并在 获取(fetching) blob URL 时确定 Content-Type 标头。

3.3. 方法与参数

3.3.1. slice() 方法

slice() 方法返回一个新的 Blob 对象,其中包含从可选的 start 参数范围到但不包括可选的 end 参数的字节,并且具有一个 type 属性,该属性为可选的 contentType 参数的值。它必须按如下方式执行:
  1. sliceStartsliceEndsliceContentType 为 null。

  2. 如果给出了 start,将 sliceStart 设置为 start

  3. 如果给出了 end,将 sliceEnd 设置为 end

  4. 如果给出了 contentType,将 sliceContentType 设置为 contentType

  5. 返回给定 thissliceStartsliceEndsliceContentType切片 blob 的结果。

下面的示例说明了可能的不同 slice() 调用类型。由于 File 接口继承自 Blob 接口,因此示例基于 File 接口的使用。
// obtain input element through DOM

var file = document.getElementById('file').files[0];
if(file)
{
  // create an identical copy of file
  // the two calls below are equivalent

  var fileClone = file.slice();
  var fileClone2 = file.slice(0, file.size);

  // slice file into 1/2 chunk starting at middle of file
  // Note the use of negative number

  var fileChunkFromEnd = file.slice(-(Math.round(file.size/2)));

  // slice file into 1/2 chunk starting at beginning of file

  var fileChunkFromStart = file.slice(0, Math.round(file.size/2));

  // slice file from beginning till 150 bytes before end

  var fileNoMetadata = file.slice(0, -150, "application/experimental");
}

3.3.2. stream() 方法

stream() 方法在调用时,必须返回对 this 调用 获取流(get stream) 的结果。

3.3.3. text() 方法

text() 方法在调用时,必须运行这些步骤:

  1. stream 为对 this 调用 获取流 的结果。

  2. reader 为从 stream 获取读取器(getting a reader) 的结果。如果这抛出了异常,则返回一个被该异常拒绝的新 Promise。

  3. promise 为使用 readerstream 读取所有字节(reading all bytes) 的结果。

  4. 返回通过一个 fulfillment 处理程序转换 promise 的结果,该处理程序返回对其第一个参数运行 UTF-8 解码 的结果。

注意:这与 readAsText() 的行为不同,以便更好地与 Fetch 的 text() 行为保持一致。具体而言,此方法将始终使用 UTF-8 作为编码,而 FileReader 可以根据 blob 的类型和传入的编码名称使用不同的编码。

3.3.4. arrayBuffer() 方法

arrayBuffer() 方法在调用时,必须运行这些步骤:

  1. stream 为对 this 调用 获取流 的结果。

  2. reader 为从 stream 获取读取器 的结果。如果这抛出了异常,则返回一个被该异常拒绝的新 Promise。

  3. promise 为使用 readerstream 读取所有字节 的结果。

  4. 返回通过一个 fulfillment 处理程序转换 promise 的结果,该处理程序返回一个内容为该 fulfillment 处理程序第一个参数的新 ArrayBuffer

3.3.5. bytes() 方法

bytes() 方法在调用时,必须运行这些步骤:

  1. stream 为对 this 调用 获取流 的结果。

  2. reader 为从 stream 获取读取器 的结果。如果这抛出了异常,则返回一个被该异常拒绝的新 Promise。

  3. promise 为使用 readerstream 读取所有字节 的结果。

  4. 返回通过一个 fulfillment 处理程序转换 promise 的结果,该处理程序返回一个包装了包含其第一个参数的 ArrayBuffer 的新 Uint8Array

4. File 接口

File 对象是一个带有 name 属性的 Blob 对象(该属性为字符串);它可以通过构造函数在 Web 应用中创建,或者是指代来自底层(OS)文件系统的文件 字节 序列的引用。

如果 File 对象是指代源自磁盘文件的 字节 序列的引用,则其 快照状态 应设置为 File 对象创建时磁盘上文件的状态。

注意:对于用户代理而言,这是一项非平凡的实现需求,因此这不是一项 *必须(must)* 而是 *应该(should)* [RFC2119] 的要求。用户代理应努力使 File 对象的 快照状态 在获取引用时设置为底层存储在磁盘上的状态。如果在获取引用后文件在磁盘上被修改,则 File快照状态 将与底层存储的状态不同。用户代理可以使用修改时间戳和其他机制来维持 快照状态,但这留作实现细节。

File 对象指代磁盘上的文件时,用户代理必须返回该文件的 type,并且必须遵循下方的 文件类型指南(file type guidelines)

[Exposed=(Window,Worker), Serializable]
interface File : Blob {
  constructor(sequence<BlobPart> fileBits,
              USVString fileName,
              optional FilePropertyBag options = {});
  readonly attribute DOMString name;
  readonly attribute long long lastModified;
};

dictionary FilePropertyBag : BlobPropertyBag {
  long long lastModified;
};

File 对象是 可序列化对象。给定 valueserialized,其 序列化步骤 为:

  1. serialized.[[SnapshotState]] 设置为 value快照状态

  2. serialized.[[ByteSequence]] 设置为 value 的底层字节序列。

  3. serialized.[[Name]] 设置为 valuename 属性的值。

  4. serialized.[[LastModified]] 设置为 valuelastModified 属性的值。

给定 valueserialized,其 反序列化步骤 为:

  1. value快照状态 设置为 serialized.[[SnapshotState]]。

  2. value 的底层字节序列设置为 serialized.[[ByteSequence]]。

  3. valuename 属性的值初始化为 serialized.[[Name]]。

  4. valuelastModified 属性的值初始化为 serialized.[[LastModified]]。

4.1. 构造函数

File 构造函数使用两个或三个参数调用,具体取决于是否使用了可选的字典参数。当调用 File() 构造函数时,用户代理必须运行以下步骤:
  1. bytes 为给定 fileBitsoptions 处理 blob 部分 的结果。

  2. n 为传递给构造函数的 fileName 参数。

    注意:底层操作系统文件系统对文件名使用不同的约定;对于构造的文件,强制使用 UTF-16 可减少文件名转换为 字节 序列时的歧义。

  3. 通过运行以下子步骤处理 FilePropertyBag 字典参数:

    1. 如果提供了 type 成员且不是空字符串,则令 t 设置为 type 字典成员。如果 t 包含 U+0020 到 U+007E 范围之外的任何字符,则将 t 设置为空字符串并从这些子步骤返回。

    2. t 中的每个字符转换为 ASCII 小写

    3. 如果提供了 lastModified 成员,令 d 设置为 lastModified 字典成员。如果未提供,将 d 设置为当前的日期和时间,表示为自 Unix 纪元 以来的毫秒数(这等同于 Date.now() [ECMA-262])。

      注意:由于 ECMA-262 Date 对象转换为表示自 Unix 纪元 以来毫秒数的 long long 值,因此 lastModified 成员可以是 Date 对象 [ECMA-262]

  4. 返回一个新的 File 对象 F,使得:

    1. F 指代 bytes 字节 序列。

    2. F.size 设置为 bytes 中的总字节数。

    3. F.name 设置为 n

    4. F.type 设置为 t

    5. F.lastModified 设置为 d

4.1.1. 构造函数参数

File() 构造函数可以使用以下参数调用:

一个 fileBits 序列(sequence)
它接受任意数量的以下元素,并且顺序不限:
  • BufferSource 元素。

  • Blob 元素(包括 File 元素)。

  • USVString 元素。

  • 一个 fileName 参数
    一个表示文件名的 USVString 参数;此构造函数参数的规范条件可在 § 4.1 构造函数 中找到。
    一个可选的 FilePropertyBag 字典
    它除了 BlobPropertyBag成员 外,还接受一个成员:
  • 一个可选的 lastModified 成员,它必须是 long long 类型;此成员的规范条件在 § 4.1 构造函数 中提供。

  • 4.2. 属性

    name 类型为 DOMString,只读
    文件名。在获取时,这必须返回作为字符串的文件名。不同的底层操作系统文件系统使用了众多的文件名变体和约定;这仅仅是文件名,不包含路径信息。在获取时,如果用户代理无法使此信息可用,则必须返回空字符串。如果 File 对象是使用构造函数创建的,则该属性的进一步规范条件可在 § 4.1 构造函数 中找到。
    lastModified 类型为 long long,只读
    文件的最后修改日期。在获取时,如果用户代理可以使此信息可用,则必须返回一个 long long,设置为文件最后一次修改的时间,即自 Unix 纪元 以来的毫秒数。如果最后修改日期和时间未知,则该属性必须返回当前日期和时间作为代表自 Unix 纪元 以来的毫秒数的 long long 值;这等同于 Date.now() [ECMA-262]。如果 File 对象是使用构造函数创建的,则该属性的进一步规范条件可在 § 4.1 构造函数 中找到。

    File 接口在暴露类型为 FileList 属性的对象上可用;这些对象在 HTML [HTML] 中定义。File 接口继承自 Blob,它是不可变的,因此表示在启动 读取操作 时可以读入内存的文件数据。用户代理必须将那些在读取时已不存在的文件的读取处理为 错误,如果在 Web Worker [Workers] 上使用 FileReaderSync,则抛出 NotFoundError 异常;或者触发一个带有 error 属性(返回 NotFoundError)的 错误 事件。

    在下面的示例中,来自文件对象的元数据被有意义地显示,并且一个带有名称和最后修改日期的文件对象被创建。var file = document.getElementById("filePicker").files[0]; var date = new Date(file.lastModified); println("You selected the file " + file.name + " which was modified on " + date.toDateString() + "."); ... // Generate a file with a specific last modified date var d = new Date(2013, 12, 5, 16, 23, 45, 600); var generatedFile = new File(["Rough Draft ...."], "Draft1.txt", {type: "text/plain", lastModified: d}) ...

    5. The FileList Interface

    注意:FileList 接口应被视为“有风险”,因为 Web 平台的总体趋势是将此类接口替换为 ECMAScript [ECMA-262] 中的 Array 平台对象。特别是,这意味着 filelist.item(0) 这种语法是有风险的;FileList 的大多数其他编程使用不太可能受到最终迁移到 Array 类型的影响。

    此接口是 File 对象的列表。

    [Exposed=(Window,Worker), Serializable]
    interface FileList {
      getter File? item(unsigned long index);
      readonly attribute unsigned long length;
    };
    

    FileList 对象是 可序列化对象。给定 valueserialized,其 序列化步骤 为:

    1. serialized.[[Files]] 设置为一个空 列表

    2. 对于 value 中的每个 file,将 file子序列化(sub-serialization) 追加到 serialized.[[Files]] 中。

    给定 serializedvalue,其 反序列化步骤 为:

    1. 对于 serialized.[[Files]] 中的每个 file,将 file子反序列化(sub-deserialization) 添加到 value 中。

    示例用法通常涉及对表单内 <input type="file"> 元素的 DOM 访问,然后访问所选文件。// uploadData is a form element // fileChooser is input element of type 'file' var file = document.forms['uploadData']['fileChooser'].files[0]; // alternative syntax can be // var file = document.forms['uploadData']['fileChooser'].files.item(0); if(file) { // Perform file ops }

    5.1. 属性

    length 类型为 unsigned long,只读
    必须返回 FileList 对象中的文件数量。如果没有文件,该属性必须返回 0。

    5.2. 方法与参数

    item(index)
    必须返回 FileList 中的第 indexFile 对象。如果 FileList 中不存在第 indexFile 对象,则该方法必须返回 nullindex 必须由用户代理视为 FileListFile 对象位置的值,0 表示第一个文件。支持的属性索引(Supported property indices) 是范围从 0 到由 FileList 对象表示的 File 对象数量减 1 的数字。如果没有此类 File 对象,则没有支持的属性索引。

    注意:HTMLInputElement 接口具有一个类型为 FileList 的只读属性,这就是上述示例中正在访问的内容。其他具有类型为 FileList 的只读属性的接口包括 DataTransfer 接口。

    6. 读取数据

    6.1. 文件读取任务源

    本规范定义了一个新的通用 任务源(task source),称为 文件读取任务源(file reading task source),它用于本规范中所有 排队任务,以读取与 BlobFile 对象关联的字节序列。它应被用于响应异步读取二进制数据而触发的功能。

    6.2. FileReader API

    [Exposed=(Window,Worker)]
    interface FileReader: EventTarget {
      constructor();
      // async read methods
      undefined readAsArrayBuffer(Blob blob);
      undefined readAsBinaryString(Blob blob);
      undefined readAsText(Blob blob, optional DOMString encoding);
      undefined readAsDataURL(Blob blob);
    
      undefined abort();
    
      // states
      const unsigned short EMPTY = 0;
      const unsigned short LOADING = 1;
      const unsigned short DONE = 2;
    
      readonly attribute unsigned short readyState;
    
      // File or Blob data
      readonly attribute (DOMString or ArrayBuffer)? result;
    
      readonly attribute DOMException? error;
    
      // event handler content attributes
      attribute EventHandler onloadstart;
      attribute EventHandler onprogress;
      attribute EventHandler onload;
      attribute EventHandler onabort;
      attribute EventHandler onerror;
      attribute EventHandler onloadend;
    };
    

    FileReader 具有一个关联的 状态(state),即 "empty""loading""done"。它最初为 "empty"

    FileReader 具有一个关联的 结果(result)nullDOMStringArrayBuffer)。它最初为 null

    FileReader 具有一个关联的 错误(error)nullDOMException)。它最初为 null

    FileReader() 构造函数在调用时,必须返回一个新的 FileReader 对象。

    readyState 属性的 getter 在调用时,切换 this状态 并运行关联的步骤:

    "empty"

    返回 EMPTY

    "loading"

    返回 LOADING

    "done"

    返回 DONE

    result 属性的 getter 在调用时,必须返回 this结果

    error 属性的 getter 在调用时,必须返回 this错误

    FileReader fr 具有一个关联的 读取操作(read operation) 算法,给定 blob、一个 type 和一个可选的 encodingName,运行以下步骤:
  • 如果 fr状态"loading",则抛出 InvalidStateError DOMException

  • fr状态 设置为 "loading"

  • fr结果 设置为 null

  • fr错误 设置为 null

  • stream 为对 blob 调用 获取流 的结果。

  • reader 为从 stream 获取读取器 的结果。

  • bytes 为一个空 字节序列

  • chunkPromise 为使用 readerstream 读取数据块(reading a chunk) 的结果。

  • isFirstChunk 为 true。

  • 并行(In parallel) 执行,当 true 时:

    1. 等待 chunkPromise 被履行或拒绝。

    2. 如果 chunkPromise 被履行,且 isFirstChunk 为 true,则 排队一个任务,以在 fr触发一个名为 loadstart 的进度事件。

      我们可能会将 loadstart 修改为同步分发,以与 XMLHttpRequest 的行为保持一致。 [Issue #119]

    3. isFirstChunk 设置为 false。

    4. 如果 chunkPromise 被兑现(fulfilled)为一个对象,且该对象的 done 属性为 false,value 属性为一个 Uint8Array 对象,则执行以下步骤

      1. bs 为该 Uint8Array 对象所表示的 字节序列

      2. bs 追加到 bytes 中。

      3. 如果自上次调用这些步骤以来大约经过了 50 毫秒,则 排入一个任务,在 fr触发一个名为 progress 的进度事件。

      4. chunkPromise 设置为从 stream 中使用 reader 读取数据块 的结果。

    5. 否则,如果 chunkPromise 被兑现为一个 done 属性为 true 的对象,则 排入一个任务 以运行以下步骤并终止此算法

      1. fr状态 设置为 "done"

      2. result 为给定 bytestypeblobtype 以及 encodingName 进行 打包数据 的结果。

      3. 如果 打包数据 抛出了异常 error

        1. fr错误 设置为 error

        2. fr触发一个名为 error 的进度事件。

      4. 否则:

        1. fr结果 设置为 result

        2. fr触发一个名为 load 的进度事件。

      5. 如果 fr状态 不为 "loading",则在 fr触发一个名为 loadend 的进度事件。

        注:loaderror 事件的事件处理程序可能已经启动了另一次读取,如果发生这种情况,则此读取的 loadend 事件不会被触发。

    6. 否则,如果 chunkPromise 被以错误 error 拒绝(rejected),则 排入一个任务 以运行以下步骤并终止此算法

      1. fr状态 设置为 "done"

      2. fr错误 设置为 error

      3. fr触发一个名为 error 的进度事件。

      4. 如果 fr状态 不为 "loading",则在 fr触发一个名为 loadend 的进度事件。

        注:error 事件的事件处理程序可能已经启动了另一次读取,如果发生这种情况,则此读取的 loadend 事件不会被触发。

  • 文件读取任务源 用于所有这些任务。

    6.2.1. 事件处理程序内容属性

    以下是用户代理必须在 FileReader 上作为 DOM 属性支持的 事件处理程序内容属性(及其对应的 事件处理程序事件类型

    event handler content attribute 事件处理器事件类型
    onloadstart loadstart
    onprogress progress
    onabort abort (中止)
    onerror error
    onload load
    onloadend loadend

    6.2.2. FileReader 状态

    FileReader 对象可以处于 3 种状态之一。readyState 属性用于告知对象当前所处的状态。
    EMPTY(数值 0)

    FileReader 对象已被构造,且没有挂起的读取操作。尚未调用任何 读取方法。这是新创建的 FileReader 对象的默认状态,直到在其上调用了任一 读取方法

    LOADING(数值 1)

    正在读取 FileBlob。正在处理其中一个 读取方法,且在读取过程中尚未发生错误。

    DONE(数值 2)

    整个 FileBlob 已被读取到内存中,或者发生了 文件读取错误,或者已使用 abort() 中止了读取。FileReader 不再读取 FileBlob。如果 readyState 设置为 DONE,则意味着已在此 FileReader 上调用了至少一个 读取方法

    6.2.3. 读取 File 或 Blob

    FileReader 接口提供了几种 异步读取方法——readAsArrayBuffer()readAsBinaryString()readAsText()readAsDataURL(),它们将文件读入内存。

    注:如果同一 FileReader 对象上调用了多个并发读取方法,用户代理会在 readyState = LOADING 时调用的任何读取方法上抛出 InvalidStateError

    FileReaderSync 提供了几种 同步读取方法。统称为 FileReaderFileReaderSync 的同步和异步读取方法为 读取方法。)

    6.2.3.1. readAsDataURL() 方法

    readAsDataURL(blob) 方法在被调用时,必须针对 blob 发起一个带有 DataURL读取操作

    6.2.3.2. readAsText() 方法

    readAsText(blob, encoding) 方法在被调用时,必须针对 blob 发起一个带有 Textencoding读取操作

    6.2.3.3. readAsArrayBuffer() 方法

    readAsArrayBuffer(blob) 方法在被调用时,必须针对 blob 发起一个带有 ArrayBuffer读取操作

    6.2.3.4. readAsBinaryString() 方法

    readAsBinaryString(blob) 方法在被调用时,必须针对 blob 发起一个带有 BinaryString读取操作

    注:推荐使用 readAsArrayBuffer(),而非为向后兼容提供的 readAsBinaryString()

    6.2.3.5. abort() 方法

    当调用 abort() 方法时,用户代理必须运行以下步骤

    1. 如果 状态"empty""done",则将 结果 设置为 null终止此算法

    2. 如果 状态"loading",则将 状态 设置为 "done" 并将 结果 设置为 null

    3. 如果关联的 任务队列 中有任何来自 且属于 文件读取任务源任务,则将这些 任务 从该任务队列中移除。

    4. 终止 正在处理的 读取方法 的算法。

    5. 触发一个名为 abort 的进度事件。

    6. 如果 状态 不为 "loading",则在 触发一个名为 loadend 的进度事件。

    6.3. 打包数据

    Blob 有一个关联的 打包数据 算法,给定 bytes、一个 type、一个可选的 mimeType 和一个可选的 encodingName,该算法会根据 type 切换并运行相关步骤
    DataURL

    bytes 作为 DataURL [RFC2397] 返回,受以下考量因素约束

    • 如果 mimeType 可用,则按照 Data URL 规范 [RFC2397] 将其作为 Data URL 的一部分使用。

    • 如果 mimeType 不可用,则返回一个不含媒体类型的 Data URL。[RFC2397]

    更好地指定 DataURL 的生成方式。[Issue #104]

    文本
    1. encoding 为失败。

    2. 如果 encodingName 存在,则将 encoding 设置为从 encodingName 获取编码 的结果。

    3. 如果 encoding 为失败,且 mimeType 存在

      1. type 为给定 mimeType 解析 MIME 类型 的结果。

      2. 如果 type 不为失败,则将 encoding 设置为从 type参数 ["charset"] 中 获取编码 的结果。

        如果 blobtype 属性为 text/plain;charset=utf-8,则以 "utf-8" 为标签运行 获取编码。请注意,用户代理必须解析并提取构成编码 标签 的 Charset 参数部分。
    4. 如果 encoding 为失败,则将 encoding 设置为 UTF-8

    5. 使用回退编码 encoding 解码 bytes,并返回结果。

    ArrayBuffer

    返回一个新的内容为 bytesArrayBuffer

    BinaryString

    bytes 作为二进制字符串返回,其中每个字节由等值的代码单元 [0..255] 表示。

    6.4. 事件

    FileReader 对象必须是本规范中所有事件的事件目标。

    当本规范提到 称为 e触发进度事件 时(针对给定的 FileReader reader 上的某个 ProgressEvent e),以下内容具有规范性

    • 进度事件 e 不会冒泡。e.bubbles 必须为 false [DOM]

    • 进度事件 e 不可取消。e.cancelable 必须为 false [DOM]

    6.4.1. 事件摘要

    以下是 触发FileReader 对象上的事件。

    事件名称Interface触发于……
    loadstart ProgressEvent 读取开始时。
    progress ProgressEvent 读取(和解码)blob 的过程中
    abort (中止) ProgressEvent 读取已中止时。例如,通过调用 abort() 方法。
    error ProgressEvent 读取失败时(参见 文件读取错误)。
    load ProgressEvent 读取成功完成时。
    loadend ProgressEvent 请求已完成时(无论是成功还是失败)。

    6.4.2. 事件不变量摘要

    本节是资料性的。

    以下是不变量,适用于本规范中给定的异步 读取方法事件触发

    1. 一旦触发了 loadstart,相应的 loadend 就会在读取完成时触发,除非满足以下任何条件

      • 读取方法 已使用 abort() 取消,且已调用了新的 读取方法

      • load 事件的事件处理程序函数启动了新的读取

      • error 事件的事件处理程序函数启动了新的读取。

      注:事件 loadstartloadend 并非一一对应。

      此示例展示了“读取链”:在“第一次”读取继续处理的同时,从事件处理程序内部启动另一次读取。
      // In code of the sort...
      reader.readAsText(file);
      reader.onload = function(){reader.readAsText(alternateFile);}
      
      .....
      
      //... the loadend event must not fire for the first read
      
      reader.readAsText(file);
      reader.abort();
      reader.onabort = function(){reader.readAsText(updatedFile);}
      
      //... the loadend event must not fire for the first read
      
    2. blob 被完全读入内存时,将触发一个 progress 事件。

    3. loadstart 之前不会触发任何 progress 事件。

    4. abortloaderror 中的任何一个触发后,不会触发任何 progress 事件。对于给定的读取,abortloaderror 中最多触发一个。

    5. loadend 之后,不会触发 abortloaderror 事件。

    6.5. 在线程上读取

    Web Workers 允许使用同步的 FileBlob 读取 API,因为在线程上进行此类读取不会阻塞主线程。本节定义了一个同步 API,可以在 Workers [Workers] 内使用。Workers 可以同时利用异步 API(FileReader 对象) 同步 API(FileReaderSync 对象)。

    6.5.1. FileReaderSync API

    此接口提供的方法可用于 同步读取 FileBlob 对象到内存中。

    [Exposed=(DedicatedWorker,SharedWorker)]
    interface FileReaderSync {
      constructor();
      // Synchronously return strings
    
      ArrayBuffer readAsArrayBuffer(Blob blob);
      DOMString readAsBinaryString(Blob blob);
      DOMString readAsText(Blob blob, optional DOMString encoding);
      DOMString readAsDataURL(Blob blob);
    };
    
    6.5.1.1. 构造函数

    当调用 FileReaderSync() 构造函数时,用户代理必须返回一个新的 FileReaderSync 对象。

    6.5.1.2. readAsText()

    readAsText(blob, encoding) 方法在被调用时,必须运行这些步骤

    1. stream 为在 blob 上调用 get stream 的结果。

    2. reader 为从 stream获取读取器 的结果。

    3. promise 为使用 readerstream读取所有字节 的结果。

    4. 等待 promise 被兑现或拒绝。

    5. 如果 promise字节序列 bytes 被兑现

      1. 返回给定 bytesTextblobtypeencoding 进行 打包数据 的结果。

    6. 抛出 promise 的拒绝原因。

    6.5.1.3. readAsDataURL() 方法

    readAsDataURL(blob) 方法在被调用时,必须运行这些步骤

    1. stream 为在 blob 上调用 get stream 的结果。

    2. reader 为从 stream获取读取器 的结果。

    3. promise 为使用 readerstream读取所有字节 的结果。

    4. 等待 promise 被兑现或拒绝。

    5. 如果 promise字节序列 bytes 被兑现

      1. 返回给定 bytesDataURLblobtype 进行 打包数据 的结果。

    6. 抛出 promise 的拒绝原因。

    6.5.1.4. readAsArrayBuffer() 方法

    readAsArrayBuffer(blob) 方法在被调用时,必须运行这些步骤

    1. stream 为在 blob 上调用 get stream 的结果。

    2. reader 为从 stream获取读取器 的结果。

    3. promise 为使用 readerstream读取所有字节 的结果。

    4. 等待 promise 被兑现或拒绝。

    5. 如果 promise字节序列 bytes 被兑现

      1. 返回给定 bytesArrayBufferblobtype 进行 打包数据 的结果。

    6. 抛出 promise 的拒绝原因。

    6.5.1.5. readAsBinaryString() 方法

    readAsBinaryString(blob) 方法在被调用时,必须运行这些步骤

    1. stream 为在 blob 上调用 get stream 的结果。

    2. reader 为从 stream获取读取器 的结果。

    3. promise 为使用 readerstream读取所有字节 的结果。

    4. 等待 promise 被兑现或拒绝。

    5. 如果 promise字节序列 bytes 被兑现

      1. 返回给定 bytesBinaryStringblobtype 进行 打包数据 的结果。

    6. 抛出 promise 的拒绝原因。

    注:推荐使用 readAsArrayBuffer(),而非为向后兼容提供的 readAsBinaryString()

    7. 错误和异常

    文件读取错误 可能在从底层文件系统读取文件时发生。下面列出的潜在错误状况仅供 参考

    • 正在访问的 FileBlob 在调用 异步读取方法同步读取方法 时可能不存在。这可能是因为它在获取引用后被移动或删除(例如与其他应用程序并发修改)。参见 NotFoundError

    • FileBlob 可能不可读。这可能是由于在获取 FileBlob 的引用后出现了权限问题(例如与其他应用程序并发锁定)。此外,快照状态 可能已更改。参见 NotReadableError

    • 用户代理可能确定某些文件在 Web 应用程序中使用是不安全的。文件自最初选择后可能已在磁盘上发生变化,从而导致读取无效。此外,一些文件和目录结构可能被底层文件系统视为受限;尝试从中读取可能被视为违反安全规定。参见 § 9 安全与隐私考量SecurityError

    7.1. 抛出异常或返回错误

    本节是规范性的。

    读取 FileBlob 时可能会出现错误状况。

    读取操作 可能因读取 FileBlob 时的错误状况而终止;导致 get stream 算法失败的具体错误状况称为 失败原因失败原因 包括 NotFoundUnsafeFileTooManyReadsSnapshotStateFileLock

    如果由于特定的 失败原因 导致了错误,同步读取方法会 抛出 下表中对应类型的异常。

    异步读取方法使用 error 对象的 FileReader 属性,如果由于特定的 失败原因 导致了错误,该属性必须返回下表中类型最适当的 DOMException 对象,否则返回 null。

    类型描述和失败原因
    NotFoundError 如果在处理读取时无法找到 FileBlob 资源,则这是 NotFound 失败原因对于异步读取方法,error 属性必须返回 NotFoundError 异常,同步读取方法必须 抛出 NotFoundError 异常。

    SecurityError If
    • 如果确定某些文件在 Web 应用程序中访问是不安全的,则这是 UnsafeFile 失败原因

    • 如果确定对 FileBlob 资源进行了过多的读取调用,则这是 TooManyReads 失败原因

    对于异步读取方法,error 属性可能返回 SecurityError 异常,同步读取方法可能 抛出 SecurityError 异常。

    这是一个安全错误,用于未涵盖在任何其他 失败原因 中的情况。

    NotReadableError If

    对于异步读取方法,error 属性必须返回 NotReadableError 异常,同步读取方法必须 抛出 NotReadableError 异常。

    8. 用于 Blob 和 MediaSource 引用的 URL

    本节定义了一种用于引用 BlobMediaSource 对象的 URL方案(scheme)

    8.1. 引言

    本节是资料性的。

    Blob(或对象)URL 是类似 blob:http://example.com/550e8400-e29b-41d4-a716-446655440000 的 URL。这使得 BlobMediaSource 可以与其他仅被设计为配合 URL 使用的 API(例如 img 元素)集成。Blob URL 也可用于导航以及触发本地生成数据的下载。

    为此,URL 接口上暴露了两个静态方法:createObjectURL(obj)revokeObjectURL(url)。第一个方法创建了从 URLBlob 的映射,第二个方法则撤销该映射。只要映射存在,Blob 就无法被垃圾回收,因此需要确保在引用不再需要时尽快撤销 URL。当创建 URL 的全局对象消失时,所有 URL 都会被撤销。

    8.2. 模型

    每个用户代理必须维护一个 blob URL 存储blob URL 存储 是一个 映射,其中 有效的 URL 字符串blob URL 条目

    一个 blob URL 条目 由一个 对象(类型为 BlobMediaSource)和一个 环境(一个 环境设置对象)组成。

    注:规范必须使用 获取 blob 对象 算法来访问 blob URL 条目对象

    blob URL 存储 中的 (也称为 blob URL)是 有效的 URL 字符串,当被 解析 时,会得到一个 URL,其 方案 为 "blob",主机名为空,且 路径 由一个本身也是 有效 URL 字符串 的元素组成。

    要给定 blob URL 条目 blobUrlEntry 和一个 环境设置对象、“top-level-navigation” 或 “top-level-self-fetch环境获取 blob 对象,请执行以下步骤。它们返回一个 对象
    1. isAuthorized 为 true。

    2. 如果 environment 是一个 环境设置对象,则将 isAuthorized 设置为使用 blobUrlEntryenvironment 检查同分区 blob URL 使用情况 的结果。

    3. 如果 isAuthorized 为 false,则返回失败。

    4. 返回 blobUrlEntry对象

    生成一个新的 blob URL,运行以下步骤
    1. result 为空字符串。

    2. 将字符串 "blob:" 追加到 result

    3. settings当前设置对象

    4. originsettings源(origin)

    5. serializedoriginASCII 序列化

    6. 如果 serialized 为 "null",则将其设置为实现定义的值。

    7. serialized 追加到 result

    8. 将 U+0024 斜杠(/)追加到 result

    9. 生成一个 UUID [RFC4122] 作为字符串,并将其追加到 result

    10. 返回 result

    此算法可生成的 blob URL 示例为 blob:https://example.org/40a5fb5a-d56d-4a33-b4e2-0acf6a8e5f64
    要给定一个 object 向 blob URL 存储中添加条目,运行以下步骤
    1. store 为用户代理的 blob URL 存储

    2. url生成一个新的 blob URL 的结果。

    3. entry 为由 object当前设置对象 组成的新 blob URL 条目

    4. 设置 store[url] 为 entry

    5. 返回 url

    要给定一个 url 从 blob URL 存储中移除条目,运行以下步骤
    1. store 为用户代理的 blob URL 存储

    2. url string序列化 url 的结果。

    3. 移除 store[url string]。

    8.3. blob URL 的解引用模型

    要给定一个 URL url解析 blob URL
    1. 断言url方案 为 "blob"。

    2. store 为用户代理的 blob URL 存储

    3. url string序列化 url(设置 排除片段标志)的结果。

    4. 如果 store[url string] 存在,则返回 store[url string];否则返回失败。

    blob URL 的解析和获取模型的进一步要求定义在 [URL][Fetch] 规范中。

    8.3.1. blob URL 的源

    本节是资料性的。

    只要 blob URL 尚未被撤销,其源始终与创建该 URL 的环境相同。这是通过 [URL] 规范在解析 URL 时查找 blob URL 存储 中的 URL,并使用该条目返回正确的源来实现的。

    如果 URL 被撤销,源的序列化仍将保持与创建该 blob URL 的环境的源的序列化相同,但对于不透明(opaque)源,源本身可能会有所不同。不过这种差异是不可观察的,因为撤销后的 blob URL 无论如何都无法再被解析/获取。

    8.3.2. blob URL 的访问限制

    Blob URL 只能从 存储键 与创建该 blob URL 的环境匹配的环境中获取。Blob URL 导航不受此限制。

    要给定 blob URL 条目 blobUrlEntry环境设置对象 environment检查同分区 blob URL 使用情况,请执行以下步骤。它们返回一个布尔值。
    1. blobStorageKey 为使用 blobUrlEntry环境 获取非存储用途的存储键 的结果。

    2. environmentStorageKey 为使用 environment 获取非存储用途的存储键 的结果。

    3. 如果 blobStorageKeyenvironmentStorageKey 不相等,则返回 false。

    4. 返回 true。

    8.3.3. blob URL 的生命周期

    本规范通过以下步骤扩展了 卸载文档清理步骤

    1. environmentDocument相关设置对象

    2. store 为用户代理的 blob URL 存储

    3. store 中移除 环境 等于 environment 的所有条目。

    当 worker 卸载时,这也需要一个类似的钩子。

    8.4. 创建和撤销 blob URL

    Blob URL 是使用 URL 对象上暴露的静态方法创建和撤销的。撤销 blob URL 会解除 blob URL 与其所指资源之间的关联,如果在此之后进行解引用,用户代理必须表现得就像发生了 网络错误 一样。本节描述了对 URL 规范 [URL] 的补充接口,并介绍了 blob URL 的创建和撤销方法。

    [Exposed=(Window,DedicatedWorker,SharedWorker)]
    partial interface URL {
      static DOMString createObjectURL((Blob or MediaSource) obj);
      static undefined revokeObjectURL(DOMString url);
    };
    
    createObjectURL(obj) 静态方法必须返回 向 blob URL 存储中添加条目 以获取 obj 的结果。
    revokeObjectURL(url) 静态方法必须运行这些步骤
    1. urlRecord解析 url 的结果。

    2. 如果 urlRecord方案 不为 "blob",则返回。

    3. entryurlRecordblob URL 条目

    4. 如果 entry 为 null,则返回。

    5. isAuthorized 为使用 entry当前设置对象 检查同分区 blob URL 使用情况 的结果。

    6. 如果 isAuthorized 为 false,则返回。

    7. 从 Blob URL 存储中移除条目 以获取 url

    注:这意味着尝试撤销一个未注册或从不同存储分区的环境注册的 URL 将静默失败,而不是抛出某种错误。如果发生这种情况,用户代理可能会在错误控制台中显示消息。

    注:在 URL 被撤销后尝试对其进行解引用将导致 网络错误。在 url 被撤销之前启动的请求仍应成功。

    在下例中,window1window2 是独立的,但在 同源 中;window2 可以是 window1 内部的一个 iframemyurl = window1.URL.createObjectURL(myblob); window2.URL.revokeObjectURL(myurl);

    由于用户代理拥有一个全局的 blob URL 存储,因此可以从与创建时不同的窗口撤销对象 URL。URL.revokeObjectURL() 调用确保后续对 myurl 的解引用导致用户代理表现得就像发生了 网络错误 一样。

    8.4.1. blob URL 创建和撤销示例

    Blob URL 是用于 获取 Blob 对象的字符串,并且只要它们是从中通过 URL.createObjectURL() 铸造的 document 存在,它们就可以保持存在——参见 § 8.3.3 blob URL 的生命周期

    本节给出了 blob URL 创建和撤销的使用示例及说明。

    在下例中,两个 img 元素 [HTML] 引用了相同的 blob URLurl = URL.createObjectURL(blob); img1.src = url; img2.src = url;
    在下例中,明确调用了 URL.revokeObjectURL()var blobURLref = URL.createObjectURL(file); img1 = new Image(); img2 = new Image(); // Both assignments below work as expected img1.src = blobURLref; img2.src = blobURLref; // ... Following body load // Check if both images have loaded if(img1.complete && img2.complete) { // Ensure that subsequent refs throw an exception URL.revokeObjectURL(blobURLref); } else { msg("Images cannot be previewed!"); // revoke the string-based reference URL.revokeObjectURL(blobURLref); }

    上述示例允许对单个 blob URL 进行多次引用,并且 Web 开发人员在两个图像对象加载完成后撤销该 blob URL 字符串。虽然不限制 blob URL 的使用次数提供了更大的灵活性,但它增加了泄漏的可能性;开发人员应将其与 URL.revokeObjectURL() 的相应调用配对使用。

    9. 安全与隐私考量

    本节是资料性的。

    本规范允许 Web 内容读取底层文件系统中的文件,并提供了一种通过唯一标识符访问文件的方法,因此需要考虑一些安全问题。本规范还假定主要的用户交互是通过 HTML 表单的 <input type="file"/> 元素 [HTML] 进行的,并且所有由 FileReader 对象读取的文件均已先由用户选择。重要的安全考量包括防止恶意文件选择攻击(选择循环)、防止对系统敏感文件的访问,以及防范文件在被选中后在磁盘上被篡改。

    防止选择循环

    在文件选择期间,用户可能会被与 <input type="file"/> 相关联的文件选择器轰炸(处于一种强制在关闭文件选择器前进行选择的“必须选择”循环中),用户代理可以通过使返回的 FileList 对象大小为 0 来防止对任何选定内容的文件访问。

    系统敏感文件

    (例如 /usr/bin 中的文件、密码文件以及其他原生操作系统可执行文件)通常不应暴露给 Web 内容,也不应通过 blob URL 访问。对于同步读取方法,用户代理可以 抛出 SecurityError 异常;对于异步读取,则可以返回 SecurityError 异常。

    本节为临时性内容;后续草案中可能会补充更多安全数据。

    10. 需求与用例

    本节涵盖了此 API 的需求,并阐述了一些用例。此版本的 API 未能满足所有用例;后续版本可能会选择解决这些问题。

    • 一旦用户授予权限,用户代理应提供以编程方式直接从本地文件读取和解析数据的能力。

      歌词查看器。用户想要从其 plist 文件中的歌曲中读取歌词。用户浏览并找到 plist 文件。文件被打开、读取、解析,并作为 Web 应用内可排序、可操作的列表呈现给用户。用户可以选择歌曲以获取歌词。用户使用“浏览文件”对话框。
    • 数据应能存储在本地以供日后使用,这对 Web 应用的离线数据访问非常有用。

      日历应用。用户的公司有一个日历。用户希望将本地事件同步到公司日历,标记为“忙碌”时段(不泄露个人信息)。用户浏览并选择文件。text/calendar 文件在浏览器中被解析,允许用户将文件合并为一个日历视图。然后用户希望将文件保存回其本地日历文件(使用“另存为”?)。用户还可以异步地将整合后的日历文件发送回服务器的日历存储中。
    • 用户代理应提供在给定数据量和文件名的情况下,以编程方式保存本地文件的能力。

      注意: 虽然本规范没有提供触发下载的显式 API 调用,但 HTML5 规范已经解决了这个问题。download 属性的 a 元素会启动下载,以指定名称保存一个 File。此 API 与 a 元素上的 download 属性的组合,允许在 Web 应用内创建文件,并能够将其保存在本地。

      电子表格应用。用户与表单交互并生成一些输入。然后,表单为用户生成一个 CSV(逗号分隔值)输出,供其导入电子表格,并使用“保存...”。生成的输出也可以直接集成到基于 Web 的电子表格中,并异步上传。
    • 用户代理应提供一种简化的、以编程方式将数据从文件发送到远程服务器的能力,该能力应比当今基于表单的上传更高效。

      视频/照片上传应用。用户能够选择大文件进行上传,这些文件随后可以“分块传输”到服务器。
    • 用户代理应提供一个暴露给脚本的 API 来实现上述功能。任何与文件系统的交互都会通过 UI 通知用户,给予用户完全取消或中止交易的能力。用户会收到任何文件选择的通知,并可以取消这些选择。在没有用户干预的情况下,不会静默调用这些 API。

    致谢

    本规范最初由 SVG 工作组开发。非常感谢 Mark Baker 和 Anne van Kesteren 的反馈。

    感谢 Robin Berjon、Jonas Sicking 和 Vsevolod Shmyroff 编辑了最初的规范。

    特别感谢 Olli Pettay、Nikunj Mehta、Garrett Smith、Aaron Boodman、Michael Nordman、Jian Li、Dmitry Titov、Ian Hickson、Darin Fisher、Sam Weinig、Adrian Bateman 和 Julian Reschke。

    感谢 W3C WebApps WG 以及 public-webapps@w3.org 邮件列表的参与者。

    一致性

    文档约定

    一致性要求通过描述性断言和 RFC 2119 术语相结合来表达。本文档规范性部分中的关键词“MUST”(必须)、“MUST NOT”(不得)、“REQUIRED”(必需)、“SHALL”(应)、“SHALL NOT”(不应)、“SHOULD”(推荐)、“SHOULD NOT”(不推荐)、“RECOMMENDED”(建议)、“MAY”(可以)和“OPTIONAL”(可选)应按照 RFC 2119 中的描述进行解释。然而,为了可读性,这些词在本文档中不以全大写形式出现。

    本规范的所有文本均为规范性文本,明确标记为非规范性的部分、示例和注释除外。 [RFC2119]

    本规范中的示例均以“例如”一词引入,或者通过 class="example" 与规范性文本隔开,如下所示

    这是一个说明性示例。

    说明性注释以“Note”一词开头,并使用 class="note" 与规范性文本隔开,如下所示

    注意,这是一个说明性注释。

    一致性算法

    作为算法一部分的祈使语气要求(例如“去除任何前导空格字符”或“返回 false 并中止这些步骤”)应根据引入算法时使用的关键词(“必须”、“应该”、“可以”等)进行解释。

    以算法或具体步骤表述的一致性要求可以用任何方式实现,只要最终结果等效即可。特别地,本规范定义的算法旨在易于理解,而不旨在提高性能。鼓励实现者进行优化。

    索引

    本规范定义的术语

    通过引用定义的术语

    引用

    规范性引用

    [DOM]
    Anne van Kesteren. DOM 标准. Living Standard. URL: https://dom.spec.whatwg.org/
    [ECMA-262]
    ECMAScript 语言规范. URL: https://tc39.es/ecma262/multipage/
    [ENCODING]
    Anne van Kesteren. 编码标准. Living Standard. URL: https://encoding.spec.whatwg.org/
    [Fetch]
    Anne van Kesteren. 提取标准 (Fetch Standard). 生活标准. URL: https://fetch.spec.whatwg.org/
    [HTML]
    Anne van Kesteren; et al. HTML 标准. Living Standard. URL: https://html.whatwg.cn/multipage/
    [INFRA]
    Anne van Kesteren; Domenic Denicola. Infra 标准. Living Standard. URL: https://infra.spec.whatwg.org/
    [MEDIA-SOURCE-2]
    Jean-Yves Avenard; Mark Watson. 媒体源扩展™. 2025 年 11 月 4 日. WD. URL: https://w3org.cn/TR/media-source-2/
    [MIMESNIFF]
    Gordon P. Hemsley. MIME 嗅探标准. 活标准. URL: https://mimesniff.spec.whatwg.org/
    [RFC2119]
    S. Bradner. RFC 中用于指示要求级别的关键词. 1997年3月. Best Current Practice. URL: https://datatracker.ietf.org/doc/html/rfc2119
    [RFC2397]
    L. Masinter. "data" URL 方案. 1998 年 8 月. 建议标准. URL: https://www.rfc-editor.org/rfc/rfc2397
    [RFC4122]
    K. Davis; B. Peabody; P. Leach. 通用唯一标识符 (UUIDs). 2024 年 5 月. 建议标准. URL: https://www.rfc-editor.org/rfc/rfc9562
    [STORAGE]
    Anne van Kesteren. 存储标准. 生活标准. URL: https://storage.spec.whatwg.org/
    [STREAMS]
    Adam Rice; 等人. 流标准. 活标准. URL: https://streams.spec.whatwg.org/
    [URL]
    Anne van Kesteren. URL 标准. 生活标准. URL: https://url.spec.whatwg.org/
    [WebIDL]
    Edgar Chen; Timothy Gu. Web IDL 标准. Living Standard. URL: https://webidl.spec.whatwg.org/
    [XHR]
    Anne van Kesteren. XMLHttpRequest 标准. Living Standard. URL: https://xhr.spec.whatwg.org/

    参考资料

    [Workers]
    Ian Hickson. Web Workers. 2021 年 1 月 28 日. 注意. URL: https://w3org.cn/TR/workers/

    IDL 索引

    [Exposed=(Window,Worker), Serializable]
    interface Blob {
      constructor(optional sequence<BlobPart> blobParts,
                  optional BlobPropertyBag options = {});
    
      readonly attribute unsigned long long size;
      readonly attribute DOMString type;
    
      // slice Blob into byte-ranged chunks
      Blob slice(optional [Clamp] long long start,
                optional [Clamp] long long end,
                optional DOMString contentType);
    
      // read from the Blob.
      [NewObject] ReadableStream stream();
      [NewObject] Promise<USVString> text();
      [NewObject] Promise<ArrayBuffer> arrayBuffer();
      [NewObject] Promise<Uint8Array> bytes();
    };
    
    enum EndingType { "transparent", "native" };
    
    dictionary BlobPropertyBag {
      DOMString type = "";
      EndingType endings = "transparent";
    };
    
    typedef (BufferSource or Blob or USVString) BlobPart;
    
    [Exposed=(Window,Worker), Serializable]
    interface File : Blob {
      constructor(sequence<BlobPart> fileBits,
                  USVString fileName,
                  optional FilePropertyBag options = {});
      readonly attribute DOMString name;
      readonly attribute long long lastModified;
    };
    
    dictionary FilePropertyBag : BlobPropertyBag {
      long long lastModified;
    };
    
    [Exposed=(Window,Worker), Serializable]
    interface FileList {
      getter File? item(unsigned long index);
      readonly attribute unsigned long length;
    };
    
    [Exposed=(Window,Worker)]
    interface FileReader: EventTarget {
      constructor();
      // async read methods
      undefined readAsArrayBuffer(Blob blob);
      undefined readAsBinaryString(Blob blob);
      undefined readAsText(Blob blob, optional DOMString encoding);
      undefined readAsDataURL(Blob blob);
    
      undefined abort();
    
      // states
      const unsigned short EMPTY = 0;
      const unsigned short LOADING = 1;
      const unsigned short DONE = 2;
    
      readonly attribute unsigned short readyState;
    
      // File or Blob data
      readonly attribute (DOMString or ArrayBuffer)? result;
    
      readonly attribute DOMException? error;
    
      // event handler content attributes
      attribute EventHandler onloadstart;
      attribute EventHandler onprogress;
      attribute EventHandler onload;
      attribute EventHandler onabort;
      attribute EventHandler onerror;
      attribute EventHandler onloadend;
    };
    
    [Exposed=(DedicatedWorker,SharedWorker)]
    interface FileReaderSync {
      constructor();
      // Synchronously return strings
    
      ArrayBuffer readAsArrayBuffer(Blob blob);
      DOMString readAsBinaryString(Blob blob);
      DOMString readAsText(Blob blob, optional DOMString encoding);
      DOMString readAsDataURL(Blob blob);
    };
    
    [Exposed=(Window,DedicatedWorker,SharedWorker)]
    partial interface URL {
      static DOMString createObjectURL((Blob or MediaSource) obj);
      static undefined revokeObjectURL(DOMString url);
    };
    
    

    问题索引

    我们需要更具体地说明从 Blob 读取的实际行为,可能发生的错误,可能还有关于块大小等的信息。
    我们可能会更改 loadstart 为同步分发,以与 XMLHttpRequest 行为保持一致。 [Issue #119]
    更好地指定 DataURL 的生成方式。 [Issue #104]
    当 worker 卸载时,这里需要一个类似的钩子。
    本节为临时性内容;后续草案中可能会补充更多安全数据。
    MDN

    Blob/Blob

    在所有当前引擎中。

    Firefox13+Safari6+Chrome20+
    Opera12+Edge79+
    Edge (Legacy)12+IE10+
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile12+
    Node.js15.7.0+
    MDN

    Blob/arrayBuffer

    在所有当前引擎中。

    Firefox69+Safari14+Chrome76+
    Opera?Edge79+
    Edge (旧版)?IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    Node.js15.7.0+
    MDN

    Blob/size

    在所有当前引擎中。

    Firefox4+Safari6+Chrome5+
    Opera11+Edge79+
    Edge (Legacy)12+IE10+
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile11+
    Node.js15.7.0+
    MDN

    Blob/slice

    在所有当前引擎中。

    Firefox13+Safari7+Chrome21+
    Opera12+Edge79+
    Edge (Legacy)12+IE10+
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile12+
    Node.js15.7.0+
    MDN

    Blob/stream

    在所有当前引擎中。

    Firefox69+Safari14.1+Chrome76+
    Opera?Edge79+
    Edge (旧版)?IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    Node.js15.7.0+
    MDN

    Blob/text

    在所有当前引擎中。

    Firefox69+Safari14+Chrome76+
    Opera?Edge79+
    Edge (旧版)?IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    Node.js15.7.0+
    MDN

    Blob/type

    在所有当前引擎中。

    Firefox4+Safari6+Chrome5+
    Opera11+Edge79+
    Edge (Legacy)12+IE10+
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile11+
    Node.js15.7.0+

    File/type

    在所有当前引擎中。

    Firefox3.6+Safari8+Chrome13+
    Opera15+Edge79+
    Edge (Legacy)12+IE10+
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView37+Samsung Internet?Opera Mobile14+
    MDN
    MDN

    File/File

    在所有当前引擎中。

    Firefox28+Safari10.1+Chrome38+
    Opera?Edge79+
    Edge (旧版)?IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    File/lastModified

    在所有当前引擎中。

    Firefox15+Safari10+Chrome13+
    Opera15+Edge79+
    Edge (旧版)18IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView37+Samsung Internet?Opera Mobile14+
    MDN

    File/name

    在所有当前引擎中。

    Firefox3.6+Safari8+Chrome13+
    Opera15+Edge79+
    Edge (Legacy)12+IE10+
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView37+Samsung Internet?Opera Mobile14+
    MDN
    MDN

    FileList/item

    在所有当前引擎中。

    Firefox3+Safari4+Chrome2+
    Opera12.1+Edge79+
    Edge (Legacy)12+IE10+
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView37+Samsung Internet?Opera Mobile12.1+
    MDN

    FileList/length

    在所有当前引擎中。

    Firefox3+Safari4+Chrome2+
    Opera11.1+Edge79+
    Edge (Legacy)12+IE10+
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView37+Samsung Internet?Opera Mobile11.1+
    MDN

    FileList

    在所有当前引擎中。

    Firefox3+Safari4+Chrome2+
    Opera11.1+Edge79+
    Edge (Legacy)12+IE10+
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView37+Samsung Internet?Opera Mobile11.1+
    MDN

    FileReader/FileReader

    在所有当前引擎中。

    Firefox3.6+Safari6+Chrome6+
    Opera12.1+Edge79+
    Edge (Legacy)12+IE10+
    Firefox for Android32+iOS Safari?Chrome for Android?Android WebView3+Samsung Internet?Opera Mobile12.1+
    MDN

    FileReader/abort

    在所有当前引擎中。

    Firefox3.6+Safari6+Chrome6+
    Opera11+Edge79+
    Edge (Legacy)12+IE10+
    Firefox for Android32+iOS Safari?Chrome for Android?Android WebView3+Samsung Internet?Opera Mobile11+
    MDN

    FileReader/abort_event

    在所有当前引擎中。

    Firefox3.6+Safari6+Chrome6+
    Opera11+Edge79+
    Edge (Legacy)12+IE10+
    Firefox for Android32+iOS Safari?Chrome for Android?Android WebView3+Samsung Internet?Opera Mobile11+
    MDN

    FileReader/abort_event

    在所有当前引擎中。

    Firefox3.6+Safari6+Chrome6+
    Opera11+Edge79+
    Edge (Legacy)12+IE10+
    Firefox for Android32+iOS Safari?Chrome for Android?Android WebView3+Samsung Internet?Opera Mobile11+
    MDN

    FileReader/error

    在所有当前引擎中。

    Firefox3.6+Safari6+Chrome6+
    Opera11+Edge79+
    Edge (Legacy)12+IE10+
    Firefox for Android32+iOS Safari?Chrome for Android?Android WebView3+Samsung Internet?Opera Mobile11+
    MDN

    FileReader/error_event

    在所有当前引擎中。

    Firefox3.6+Safari6+Chrome6+
    Opera11+Edge79+
    Edge (Legacy)12+IE10+
    Firefox for Android32+iOS Safari?Chrome for Android?Android WebView3+Samsung Internet?Opera Mobile11+
    MDN

    FileReader/error_event

    在所有当前引擎中。

    Firefox3.6+Safari6+Chrome6+
    Opera11+Edge79+
    Edge (Legacy)12+IE10+
    Firefox for Android32+iOS Safari?Chrome for Android?Android WebView3+Samsung Internet?Opera Mobile11+
    MDN

    FileReader/load_event

    在所有当前引擎中。

    Firefox3.6+Safari6+Chrome6+
    Opera11+Edge79+
    Edge (Legacy)12+IE10+
    Firefox for Android32+iOS Safari?Chrome for Android?Android WebView3+Samsung Internet?Opera Mobile11+
    MDN

    FileReader/load_event

    在所有当前引擎中。

    Firefox3.6+Safari6+Chrome6+
    Opera11+Edge79+
    Edge (Legacy)12+IE10+
    Firefox for Android32+iOS Safari?Chrome for Android?Android WebView3+Samsung Internet?Opera Mobile11+
    MDN

    FileReader/loadend_event

    在所有当前引擎中。

    Firefox3.6+Safari6+Chrome6+
    Opera11+Edge79+
    Edge (Legacy)12+IE10+
    Firefox for Android32+iOS Safari?Chrome for Android?Android WebView3+Samsung Internet?Opera Mobile11+
    MDN

    FileReader/loadend_event

    在所有当前引擎中。

    Firefox3.6+Safari6+Chrome6+
    Opera11+Edge79+
    Edge (Legacy)12+IE10+
    Firefox for Android32+iOS Safari?Chrome for Android?Android WebView3+Samsung Internet?Opera Mobile11+
    MDN

    FileReader/loadstart_event

    在所有当前引擎中。

    Firefox79+Safari6+Chrome6+
    Opera11+Edge79+
    Edge (Legacy)12+IE10+
    Firefox for Android79+iOS Safari?Chrome for Android?Android WebView3+Samsung Internet?Opera Mobile11+
    MDN

    FileReader/loadstart_event

    在所有当前引擎中。

    Firefox79+Safari6+Chrome6+
    Opera11+Edge79+
    Edge (Legacy)12+IE10+
    Firefox for Android79+iOS Safari?Chrome for Android?Android WebView3+Samsung Internet?Opera Mobile11+
    MDN

    FileReader/progress_event

    在所有当前引擎中。

    Firefox3.6+Safari6+Chrome6+
    Opera11+Edge79+
    Edge (Legacy)12+IE10+
    Firefox for Android32+iOS Safari?Chrome for Android?Android WebView3+Samsung Internet?Opera Mobile11+
    MDN

    FileReader/progress_event

    在所有当前引擎中。

    Firefox3.6+Safari6+Chrome6+
    Opera11+Edge79+
    Edge (Legacy)12+IE10+
    Firefox for Android32+iOS Safari?Chrome for Android?Android WebView3+Samsung Internet?Opera Mobile11+
    MDN

    FileReader/readAsArrayBuffer

    在所有当前引擎中。

    Firefox3.6+Safari6+Chrome6+
    Opera12+Edge79+
    Edge (Legacy)12+IE10+
    Firefox for Android32+iOS Safari?Chrome for Android?Android WebView3+Samsung Internet?Opera Mobile12+
    MDN

    FileReader/readAsBinaryString

    在所有当前引擎中。

    Firefox3.6+Safari6+Chrome6+
    Opera11+Edge79+
    Edge (旧版)12+IE
    Firefox for Android32+iOS Safari?Chrome for Android?Android WebView3+Samsung Internet?Opera Mobile11+
    MDN

    FileReader/readAsDataURL

    在所有当前引擎中。

    Firefox3.6+Safari6+Chrome6+
    Opera11+Edge79+
    Edge (Legacy)12+IE10+
    Firefox for Android32+iOS Safari?Chrome for Android?Android WebView3+Samsung Internet?Opera Mobile11+
    MDN

    FileReader/readAsText

    在所有当前引擎中。

    Firefox3.6+Safari6+Chrome6+
    Opera11+Edge79+
    Edge (Legacy)12+IE10+
    Firefox for Android32+iOS Safari?Chrome for Android?Android WebView3+Samsung Internet?Opera Mobile11+
    MDN

    FileReader/readyState

    在所有当前引擎中。

    Firefox3.6+Safari6+Chrome6+
    Opera11+Edge79+
    Edge (Legacy)12+IE10+
    Firefox for Android32+iOS Safari?Chrome for Android?Android WebView3+Samsung Internet?Opera Mobile11+
    MDN

    FileReader/result

    在所有当前引擎中。

    Firefox3.6+Safari6+Chrome6+
    Opera11+Edge79+
    Edge (Legacy)12+IE10+
    Firefox for Android32+iOS Safari?Chrome for Android?Android WebView3+Samsung Internet?Opera Mobile11+
    MDN

    FileReader

    在所有当前引擎中。

    Firefox3.6+Safari6+Chrome6+
    Opera11+Edge79+
    Edge (Legacy)12+IE10+
    Firefox for Android32+iOS Safari?Chrome for Android?Android WebView3+Samsung Internet?Opera Mobile11+
    MDN

    FileReaderSync/FileReaderSync

    在所有当前引擎中。

    Firefox8+Safari6+Chrome7+
    Opera12.1+Edge79+
    Edge (Legacy)12+IE10+
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile12.1+
    MDN

    FileReaderSync/readAsArrayBuffer

    在所有当前引擎中。

    Firefox8+Safari6+Chrome9+
    Opera12.1+Edge79+
    Edge (Legacy)12+IE10+
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile12.1+
    MDN

    FileReaderSync/readAsDataURL

    在所有当前引擎中。

    Firefox8+Safari6+Chrome7+
    Opera12.1+Edge79+
    Edge (Legacy)12+IE10+
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile12.1+
    MDN

    FileReaderSync/readAsText

    在所有当前引擎中。

    Firefox8+Safari6+Chrome7+
    Opera12.1+Edge79+
    Edge (Legacy)12+IE10+
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile12.1+
    MDN

    FileReaderSync

    在所有当前引擎中。

    Firefox8+Safari6+Chrome7+
    Opera12.1+Edge79+
    Edge (Legacy)12+IE10+
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile12.1+
    MDN

    URL/createObjectURL_static

    在所有当前引擎中。

    Firefox19+Safari6+Chrome19+
    Opera?Edge79+
    Edge (Legacy)12+IE10+
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    Node.js16.7.0+
    MDN

    URL/revokeObjectURL_static

    在所有当前引擎中。

    Firefox19+Safari6+Chrome19+
    Opera?Edge79+
    Edge (Legacy)12+IE10+
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    Node.js16.7.0+