<pre class="metadata">
Indent: 2
Title: File API
Shortname: FileAPI
Level: none
Group: webapps
Editor: Marijn Kruisselbrink, Google, mek@chromium.org, w3cid 72440
Former Editor: Arun Ranganathan, Mozilla Corporation, http://arunranga.com/, arun@mozilla.com, w3cid 37240
Prepare For TR: true
Status: ED
ED: https://w3c.github.io/FileAPI/
TR: https://www.w3.org/TR/FileAPI/
Repository: w3c/FileAPI
Previous Version: https://www.w3.org/TR/2019/WD-FileAPI-20190531/
!Tests: <a href=https://github.com/web-platform-tests/wpt/tree/master/FileAPI>web-platform-tests FileAPI/</a> (<a href=https://github.com/web-platform-tests/wpt/labels/FileAPI>ongoing work</a>)
Abstract: This specification provides an API for representing file objects in web applications,
  as well as programmatically selecting them and accessing their data. This includes:

  * A {{FileList}} interface, which represents an array of individually selected files from the underlying system. The user interface for selection can be invoked via <code>&lt;input type="file"></code>, i.e. when the input element is in the <code>File Upload</code> state [[HTML]].
  * A {{Blob}} interface, which represents immutable raw binary data, and allows access to ranges of bytes within the {{Blob}} object as a separate {{Blob}}.
  * A {{File}} interface, which includes readonly informational attributes about a file such as its name and the date of the last modification (on disk) of the file.
  * A {{FileReader}} interface, which provides methods to read a {{File}} or a {{Blob}}, and an event model to obtain the results of these reads.
  * A <a section href="#url">URL scheme</a> for use with binary data such as files, so that they can be referenced within web applications.

  Additionally, this specification defines objects to be used within threaded web applications for the synchronous reading of files.

  [[#requirements]] covers the motivation behind this specification.

  This API is designed to be used in conjunction with other APIs and elements on the web platform, notably:
  {{XMLHttpRequest}} (e.g. with an overloaded {{XMLHttpRequest/send()}} method for {{File}} or {{Blob}} arguments),
  {{Worker/postMessage(message, options)|postMessage()}},
  {{DataTransfer}} (part of the drag and drop API defined in [[HTML]])
  and Web Workers.
  Additionally, it should be possible to programmatically obtain a list of files from the <{input}> element
  when it is in the <code>File Upload</code> state [[HTML]].
  These kinds of behaviors are defined in the appropriate affiliated specifications.
Status Text: Previous discussion of this specification has taken place on two other mailing lists: <a href="mailto:public-webapps@w3.org">public-webapps@w3.org</a> (<a href="http://lists.w3.org/Archives/Public/public-webapps/">archive</a>) and <a href="mailto:public-webapi@w3.org">public-webapi@w3.org</a> (<a href="http://lists.w3.org/Archives/Public/public-webapi/">archive</a>). Ongoing discussion will be on the <a href="mailto:public-webapps@w3.org">public-webapps@w3.org</a> mailing list.

  This draft consists of changes made to the previous Last Call Working Draft. Please send comments to the <a href="mailto:public-webapi@w3.org">public-webapi@w3.org</a> as described above. You can see Last Call Feedback on the W3C Wiki: <a href="http://www.w3.org/wiki/Webapps/LCWD-FileAPI-20130912">http://www.w3.org/wiki/Webapps/LCWD-FileAPI-20130912</a>

  An [implementation report](https://wpt.fyi/results/FileAPI) is automatically generated from the test suite.
Translate Ids: dictdef-blobpropertybag dfn-BlobPropertyBag, dictdef-filepropertybag dfn-FilePropertyBag, filereadersync dfn-FileReaderSync, filelist dfn-filelist, filereader dfn-filereader, file dfn-file, blob dfn-Blob, blob-section blob, file-section file
Markup Shorthands: css no, markdown yes
</pre>

<pre class="link-defaults">
spec: dom
  type:interface
    text:Document
spec: html
  type: element
    text: a
    text: iframe
spec: infra
  type: dfn
    text: list
    text: string
    text: code point
spec: streams
  type:interface
    text:ReadableStream
  type: dfn
    text: chunk
spec: url
  type: dfn
    text: url; for:/
  type: interface
    text: URL
spec: fetch
  type:interface
    text:ReadableStream
</pre>

<pre class="anchors">
spec: mimesniff; urlPrefix: https://mimesniff.spec.whatwg.org/
  type: dfn
    text: parsable mime type
spec: ecma-262; urlPrefix: http://tc39.github.io/ecma262/
  type: interface
    text: Array; url: sec-array-constructor
    text: Date; url: sec-date-constructor
spec: media-source; urlPrefix: http://w3c.github.io/media-source/
  type: interface
    text: MediaSource; url: #mediasource
</pre>

# Introduction # {#intro}

*This section is informative.*

Web applications should have the ability to manipulate as wide as possible a range of user input,
including files that a user may wish to upload to a remote server or manipulate inside a rich web application.
This specification defines the basic representations for files,
lists of files,
errors raised by access to files,
and programmatic ways to read files.
Additionally, this specification also defines an interface that represents "raw data"
which can be asynchronously processed on the main thread of conforming user agents.
The interfaces and API defined in this specification can be used with other interfaces and APIs exposed to the web platform.

The {{File}} interface represents file data typically obtained from the underlying file system,
and the {{Blob}} interface
("Binary Large Object" - a name originally introduced to web APIs in <a href="https://developers.google.com/gears/?csw=1">Google Gears</a>)
represents immutable raw data.
{{File}} or {{Blob}} reads should happen asynchronously on the main thread,
with an optional synchronous API used within threaded web applications.
An asynchronous API for reading files prevents blocking and UI "freezing" on a user agent's main thread.
This specification defines an asynchronous API based on an *event model*
to read and access a {{File}} or {{Blob}}’s data.
A {{FileReader}} object provides asynchronous read methods to access that file's data
through event handler content attributes and the firing of events.
The use of events and event handlers allows separate code blocks the ability
to monitor the *progress of the read*
(which is particularly useful for remote drives or mounted drives,
  where file access performance may vary from local drives)
and error conditions that may arise during reading of a file.
An example will be illustrative.

<div class="example">
  In the example below, different code blocks handle progress, error, and success conditions.

  <pre highlight="js">
  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 &lt; 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
    }
  }
  </pre>
</div>

# Terminology and Algorithms # {#terminology}

When this specification says to <dfn id="terminate-an-algorithm" lt="terminate an algorithm|terminate this algorithm">terminate an algorithm</dfn>
the user agent must terminate the algorithm after finishing the step it is on.
Asynchronous <a>read methods</a> defined in this specification may return before the algorithm in question is terminated,
and can be terminated by an {{FileReader/abort()}} call.

The algorithms and steps in this specification use the following mathematical operations:

* max(a,b) returns the maximum of a and b,
  and is always performed on integers as they are defined in WebIDL [[WebIDL]];
  in the case of max(6,4) the result is 6.
  This operation is also defined in ECMAScript [[!ECMA-262]].
* min(a,b) returns the minimum of a and b,
  and is always performed on integers as they are defined in WebIDL [[WebIDL]];
  in the case of min(6,4) the result is 4.
  This operation is also defined in ECMAScript [[ECMA-262]].
* Mathematical comparisons such as &lt; (less than), ≤ (less than or equal to), and > (greater than) are as in ECMAScript [[ECMA-262]].

The term <dfn id="UnixEpoch">Unix Epoch</dfn> is used in this specification to refer to the time 00:00:00 UTC on January 1 1970
(or 1970-01-01T00:00:00Z ISO 8601);
this is the same time that is conceptually "<code>0</code>" in ECMA-262 [[ECMA-262]].

<!--
████████  ██        ███████  ████████
██     ██ ██       ██     ██ ██     ██
██     ██ ██       ██     ██ ██     ██
████████  ██       ██     ██ ████████
██     ██ ██       ██     ██ ██     ██
██     ██ ██       ██     ██ ██     ██
████████  ████████  ███████  ████████
-->

# The Blob Interface and Binary Data # {#blob-section}

A {{Blob}} object refers to a <a>byte</a> sequence,
and has a {{Blob/size}} attribute which is the total number of bytes in the byte sequence,
and a {{Blob/type}} attribute,
which is an ASCII-encoded string in lower case representing the media type of the <a>byte</a> sequence.

Each {{Blob}} must have an internal <dfn id="snapshot-state" for=Blob>snapshot state</dfn>,
which must be initially set to the state of the underlying storage,
if any such underlying storage exists.
Further normative definition of <a>snapshot state</a> can be found for {{File}}s.

<xmp class="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();
};

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

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

typedef (BufferSource or Blob or USVString) BlobPart;
</xmp>

{{Blob}} objects are [=serializable objects=]. Their [=serialization steps=],
given |value| and |serialized|, are:

1. Set |serialized|.\[[SnapshotState]] to |value|'s [=snapshot state=].

2. Set |serialized|.\[[ByteSequence]] to |value|'s underlying byte sequence.

Their [=deserialization step=], given |serialized| and |value|, are:

1. Set |value|'s [=snapshot state=] to |serialized|.\[[SnapshotState]].

2. Set |value|'s underlying byte sequence to |serialized|.\[[ByteSequence]].

<div algorithm="get stream">
A {{Blob}} |blob| has an associated <dfn for=Blob>get stream</dfn> algorithm,
which runs these steps:

1. Let |stream| be the result of [=construct a ReadableStream object|constructing=] a
   {{ReadableStream}} object.
1. Run the following steps [=in parallel=]:
  1. While not all bytes of |blob| have been read:
    1. Let |bytes| be the [=byte sequence=] that results from reading a [=chunk=] from |blob|.
    1. If a [=file read error=] occured while reading |bytes|, [$ReadableStream/error$]
       |stream| with a [=failure reason=] and abort these steps.
    1. [=ReadableStream/Enqueue=] a `Uint8Array` object wrapping an `ArrayBuffer`
       containing |bytes| into |stream|.
       If that threw an exception, [$ReadableStream/error$] |stream| with that exception
       and abort these steps.

    Issue: We need to specify more concretely what reading from a Blob actually does,
    what possible errors can happen, perhaps something about chunk sizes, etc.
1. Return |stream|.

</div>

## Constructors ## {#constructorBlob}

<div algorithm="blob-constructor">
The {{Blob()}} constructor can be invoked with zero or more parameters.
When the {{Blob()}} constructor is invoked,
user agents must run the following steps:

1. If invoked with zero parameters,
  return a new {{Blob}} object consisting of 0 bytes,
  with {{Blob/size}} set to 0,
  and with {{Blob/type}} set to the empty string.

1. Let |bytes| be the result of [=processing blob parts=] given {{blobParts}} and {{Blob/Blob(blobParts, options)/options}}.

1. If the {{BlobPropertyBag/type}} member of the {{Blob/Blob(blobParts, options)/options}} argument is not the empty string,
  run the following sub-steps:

  1. Let |t| be the {{BlobPropertyBag/type}} dictionary member.
    If |t| contains any characters outside the range U+0020 to U+007E,
    then set |t| to the empty string and return from these substeps.
  1. Convert every character in |t| to [=ASCII lowercase=].

1. Return a {{Blob}} object referring to |bytes| as its associated <a>byte</a> sequence,
  with its {{Blob/size}} set to the length of |bytes|,
  and its {{Blob/type}} set to the value of |t| from the substeps above.

</div>

### Constructor Parameters ### {#constructorParams}

The {{Blob()}} constructor can be invoked with the parameters below:

<dl>
  <dt>A <dfn id="dfn-blobParts" argument for="Blob/Blob(blobParts, options)"><code>blobParts</code></dfn> <code>sequence</code>
  <dd>which takes any number of the following types of elements, and in any order:
    * {{BufferSource}} elements.
    * {{Blob}} elements.
    * {{USVString}} elements.

  <dt id="dfn-BlobPropertyBagMembers">An *optional* {{BlobPropertyBag}}
  <dd>which takes these optional members:
    * <dfn id="dfn-BPtype" dict-member for="BlobPropertyBag">type</dfn>,
      the ASCII-encoded string in lower case representing the media type of the {{Blob}}.
      Normative conditions for this member are provided in the [[#constructorBlob]].
    * <dfn dict-member for="BlobPropertyBag">endings</dfn>,
      an enum which can take the values {{"transparent"}} or {{"native"}}.
      By default this is set to {{"transparent"}}. If set to {{"native"}},
      [=convert line endings to native|line endings will be converted to native=]
      in any {{USVString}} elements in {{blobParts}}.
</dl>

<div algorithm="process-blob-parts">
To <dfn lt="process blob parts|processing blob parts">process blob parts</dfn> given a sequence of {{BlobPart}}'s |parts|
and {{BlobPropertyBag}} |options|,
run the following steps:

1. Let |bytes| be an empty sequence of bytes.

1. For each |element| in |parts|:

  1. If |element| is a {{USVString}}, run the following substeps:

    1. Let |s| be |element|.

    1. If the {{BlobPropertyBag/endings}} member of |options| is {{"native"}},
      set |s| to the result of [=converting line endings to native=] of |element|.

    1. Append the result of [=UTF-8 encoding=] |s| to |bytes|.

      Note: The algorithm from WebIDL [[WebIDL]] replaces unmatched surrogates in an invalid utf-16 string
      with U+FFFD replacement characters.
      Scenarios exist when the {{Blob}} constructor may result in some data loss
      due to lost or scrambled character sequences.

  1. If |element| is a {{BufferSource}}, <a lt="get a copy of the buffer source">get
    a copy of the bytes held by the buffer source</a>, and append those bytes to |bytes|.

  1. If |element| is a {{Blob}},
    append the bytes it represents to |bytes|.

    Note: The {{Blob/type}} of the {{Blob}} array element is ignored and will not affect {{Blob/type}} of returned
    {{Blob}} object.

1. Return |bytes|.

</div>

<div algorithm="convert-line-endings-to-native">
To <dfn lt="convert line endings to native|converting line endings to native">
convert line endings to native</dfn> in a [=string=] |s|,
run the following steps:

1. Let |native line ending| be be the [=code point=] U+000A LF.

1. If the underlying platform's conventions are
  to represent newlines as a carriage return and line feed sequence,
  set |native line ending| to the [=code point=] U+000D CR
  followed by the [=code point=] U+000A LF.

1. Set |result| to the empty [=string=].

1. Let |position| be a [=position variable=] for |s|,
  initially pointing at the start of |s|.

1. Let |token| be the result of [=collecting a sequence of code points=]
  that are not equal to U+000A LF or U+000D CR
  from |s| given |position|.

1. Append |token| to |result|.

1. While |position| is not past the end of |s|:

  1. If the [=code point=] at |position| within |s| equals U+000D CR:

    1. Append |native line ending| to |result|.

    1. Advance |position| by 1.

    1. If |position| is not past the end of |s|
      and the [=code point=] at |position| within |s| equals U+000A LF
      advance |position| by 1.

  1. Otherwise if the [=code point=] at |position| within |s| equals U+000A LF,
    advance |position| by 1 and append |native line ending| to |result|.

  1. Let |token| be the result of [=collecting a sequence of code points=]
    that are not equal to U+000A LF or U+000D CR
    from |s| given |position|.

  1. Append |token| to |result|.

1. Return |result|.

</div>

<div class="example">
  Examples of constructor usage follow.

  <pre class="lang-javascript">
  // 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]);
  </pre>
</div>

## Attributes ## {#attributes-blob}

<dl dfn-type="attribute" dfn-for="Blob">
  <dt><dfn id="dfn-size">size</dfn>
  <dd>Returns the size of the <a>byte</a> sequence in number of bytes.
    On getting, conforming user agents must return the total number of bytes that can be read by a {{FileReader}} or {{FileReaderSync}} object,
    or 0 if the {{Blob}} has no bytes to be read.

  <dt><dfn id="dfn-type">type</dfn>
  <dd>The ASCII-encoded string in lower case representing the media type of the {{Blob}}.
    On getting, user agents must return the type of a {{Blob}}
    as an ASCII-encoded string in lower case,
    such that when it is converted to a <a>byte</a> sequence,
    it is a <a>parsable MIME type</a>,
    or the empty string &ndash; 0 bytes &ndash; if the type cannot be determined.

    The {{Blob/type}} attribute can be set by the web application itself through constructor invocation
    and through the {{Blob/slice()}} call;
    in these cases, further normative conditions for this attribute are in [[#constructorBlob]],
    [[#file-constructor]],
    and [[#slice-method-algo]] respectively.
    User agents can also determine the {{Blob/type}} of a {{Blob}},
    especially if the <a>byte</a> sequence is from an on-disk file;
    in this case, further normative conditions are in the <a>file type guidelines</a>.

    Note: The type <var ignore>t</var> of a {{Blob}} is considered a <a>parsable MIME type</a>,
    if performing the <a>parse a MIME type</a> algorithm to a byte sequence converted from
    the ASCII-encoded string representing the Blob object's type does not return failure.

    Note: Use of the {{Blob/type}} attribute informs the [=package data=] algorithm
    and determines the `Content-Type` header when [=/fetching=] [=blob URLs=].
</dl>

## Methods and Parameters ## {#methodsandparams-blob}

### The {{Blob/slice()}} method ### {#slice-method-algo}

The <dfn id="dfn-slice" method for=Blob lt="slice(start, end, contentType), slice(start, end), slice(start), slice()">slice()</dfn> method
returns a new {{Blob}} object with bytes ranging from
the optional {{start}} parameter
up to but not including the optional {{end}} parameter,
and with a {{Blob/type}} attribute that is the value of the optional {{contentType!!argument}} parameter.
It must act as follows:

1. Let |O| be the {{Blob}} <a>context object</a> on which the {{slice()}} method is being called.
2. The optional <dfn argument for="Blob/slice(start, end, contentType)" id="dfn-start">start</dfn> parameter
  is a value for the start point of a {{slice()}} call,
  and must be treated as a byte-order position,
  with the zeroth position representing the first byte.
  User agents must process {{Blob/slice()}} with {{start}} normalized according to the following:

  <ol type="a">
    <li>If the optional {{start}} parameter is not used as a parameter when making this call, let |relativeStart| be 0.
    <li>If {{start}} is negative, let |relativeStart| be <code>max(({{Blob/size}} + {{start}}), 0)</code>.
    <li>Else, let |relativeStart| be <code>min(start, size)</code>.
  </ol>

3. The optional <dfn argument for="Blob/slice(start, end, contentType)" id="dfn-end">end</dfn> parameter
  is a value for the end point of a {{slice()}} call.
  User agents must process {{Blob/slice()}} with {{end}} normalized according to the following:

  <ol type="a">
    <li>If the optional {{end}} parameter is not used as a parameter when making this call, let |relativeEnd| be {{Blob/size}}.
    <li>If {{end}} is negative, let |relativeEnd| be <code>max((size + end), 0)</code>.
    <li>Else, let |relativeEnd| be <code>min(end, size)</code>.
  </ol>

4. The optional <dfn argument for="Blob/slice(start, end, contentType)" id="dfn-contentTypeBlob">contentType</dfn> parameter
  is used to set the ASCII-encoded string in lower case representing the media type of the Blob.
  User agents must process the {{Blob/slice()}} with {{contentType}} normalized according to the following:

  <ol type="a">
    <li>If the {{contentType}} parameter is not provided, let |relativeContentType| be set to the empty string.
    <li>Else let |relativeContentType| be set to {{contentType}} and run the substeps below:
      1. If |relativeContentType| contains any characters outside the range of U+0020 to U+007E,
        then set |relativeContentType| to the empty string and return from these substeps.
      2. Convert every character in |relativeContentType| to [=ASCII lowercase=].
  </ol>

5. Let |span| be <code>max((relativeEnd - relativeStart), 0)</code>.

6. Return a new {{Blob}} object |S| with the following characteristics:

  <ol type="a">
    <li>|S| refers to |span| consecutive <a>byte</a>s from |O|,
      beginning with the <a>byte</a> at byte-order position |relativeStart|.
    <li>|S|.{{Blob/size}} = |span|.
    <li>|S|.{{Blob/type}} = |relativeContentType|.
  </ol>

<div class="example">
  The examples below illustrate the different types of {{slice()}} calls possible. Since the
  {{File}} interface inherits from the {{Blob}} interface, examples are based on the use of the {{File}} interface.

  <pre class="lang-javascript">
    // 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");
    }
  </pre>
</div>

### The {{Blob/stream()}} method ### {#stream-method-algo}

The <dfn method for=Blob>stream()</dfn> method, when invoked, must return
the result of calling [=get stream=] on the [=context object=].

### The {{Blob/text()}} method ### {#text-method-algo}

The <dfn method for=Blob>text()</dfn> method, when invoked, must run these steps:

1. Let |stream| be the result of calling [=get stream=] on the [=context object=].
1. Let |reader| be the result of [=get a reader|getting a reader=] from |stream|.
   If that threw an exception, return a new promise rejected with that exception.
1. Let |promise| be the result of [=read all bytes|reading all bytes=] from |stream| with |reader|.
1. Return the result of transforming |promise| by a fulfillment handler that returns the result of
   running [=UTF-8 decode=] on its first argument.

Note: This is different from the behavior of {{FileReader/readAsText()}} to align better
with the behavior of {{Body/text()|Fetch's text()}}. Specifically this method will always
use UTF-8 as encoding, while {{FileReader}} can use a different encoding depending on
the blob's type and passed in encoding name.

### The {{Blob/arrayBuffer()}} method ### {#arraybuffer-method-algo}

The <dfn method for=Blob>arrayBuffer()</dfn> method, when invoked, must run these steps:

1. Let |stream| be the result of calling [=get stream=] on the [=context object=].
1. Let |reader| be the result of [=get a reader|getting a reader=] from |stream|.
   If that threw an exception, return a new promise rejected with that exception.
1. Let |promise| be the result of [=read all bytes|reading all bytes=] from |stream| with |reader|.
1. Return the result of transforming |promise| by a fulfillment handler that returns
   a new {{ArrayBuffer}} whose contents are its first argument.

<!--
████████ ████ ██       ████████
██        ██  ██       ██
██        ██  ██       ██
██████    ██  ██       ██████
██        ██  ██       ██
██        ██  ██       ██
██       ████ ████████ ████████
-->

# The File Interface # {#file-section}

A {{File}} object is a {{Blob}} object with a {{File/name}} attribute, which is a string;
it can be created within the web application via a constructor,
or is a reference to a <a>byte</a> sequence from a file from the underlying (OS) file system.

If a {{File}} object is a reference to a <a>byte</a> sequence originating from a file on disk,
then its <a>snapshot state</a> should be set to the state of the file on disk at the time the {{File}} object is created.

Note: This is a non-trivial requirement to implement for user agents,
and is thus not a *must* but a *should* [[RFC2119]].
User agents should endeavor to have a {{File}} object's <a>snapshot state</a>
set to the state of the underlying storage on disk at the time the reference is taken.
If the file is modified on disk following the time a reference has been taken,
the {{File}}'s <a>snapshot state</a> will differ from the state of the underlying storage.
User agents may use modification time stamps and other mechanisms to maintain <a>snapshot state</a>,
but this is left as an implementation detail.

When a {{File}} object refers to a file on disk,
user agents must return the {{Blob/type}} of that file,
and must follow the <dfn export>file type guidelines</dfn> below:

* User agents must return the {{Blob/type}} as an ASCII-encoded string in lower case,
  such that when it is converted to a corresponding byte sequence,
  it is a <a>parsable MIME type</a>,
  or the empty string &ndash; 0 bytes &ndash; if the type cannot be determined.
* When the file is of type <code>text/plain</code>
  user agents must NOT append a charset parameter to the <i>dictionary of parameters</i> portion of the media type [[!MIMESNIFF]].
* User agents must not attempt heuristic determination of encoding,
  including statistical methods.

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

dictionary FilePropertyBag : BlobPropertyBag {
  long long lastModified;
};
</pre>

{{File}} objects are [=serializable objects=]. Their [=serialization steps=],
given |value| and |serialized|, are:

1. Set |serialized|.\[[SnapshotState]] to |value|'s [=snapshot state=].

2. Set |serialized|.\[[ByteSequence]] to |value|'s underlying byte sequence.

3. Set |serialized|.\[[Name]] to the value of |value|'s {{File/name}} attribute.

4. Set |serialized|.\[[LastModified]] to the value of |value|'s {{File/lastModified}} attribute.

Their [=deserialization steps=], given |value| and |serialized|, are:

1. Set |value|'s [=snapshot state=] to |serialized|.\[[SnapshotState]].

2. Set |value|'s underlying byte sequence to |serialized|.\[[ByteSequence]].

3. Initialize the value of |value|'s {{File/name}} attribute to |serialized|.\[[Name]].

4. Initialize the value of |value|'s {{File/lastModified}} attribute to
   |serialized|.\[[LastModified]].

## Constructor ## {#file-constructor}

<div algorithm="file-constructor">
The {{File}} constructor is invoked with two or three parameters,
depending on whether the optional dictionary parameter is used.
When the {{File()}} constructor is invoked,
user agents must run the following steps:

1. Let |bytes| be the result of [=processing blob parts=] given {{fileBits}}
  and {{File/File(fileBits, fileName, options)/options}}.


2. Let |n| be a new string of the same size as the {{fileName}} argument to the constructor.
  Copy every character from {{fileName}} to |n|,
  replacing any "/" character (U+002F SOLIDUS) with a ":" (U+003A COLON).

  Note: Underlying OS filesystems use differing conventions for file name;
  with constructed files, mandating UTF-16 lessens ambiquity when file names are converted to <a>byte</a> sequences.

3. Process {{FilePropertyBag}} dictionary argument by running the following substeps:

  1. If the {{BlobPropertyBag/type}} member is provided and is not the empty string,
    let |t| be set to the {{BlobPropertyBag/type}} dictionary member.
    If |t| contains any characters outside the range U+0020 to U+007E,
    then set |t| to the empty string and return from these substeps.
  2. Convert every character in |t| to [=ASCII lowercase=].
  3. If the {{FilePropertyBag/lastModified}} member is provided,
    let |d| be set to the  {{FilePropertyBag/lastModified}} dictionary member.
    If it is not provided,
    set |d| to the current date and time
    represented as the number of milliseconds since the <a>Unix Epoch</a>
    (which is the equivalent of <code>Date.now()</code> [[ECMA-262]]).

    Note: Since ECMA-262 {{Date}} objects convert to <code>long long</code> values
    representing the number of milliseconds since the <a>Unix Epoch</a>,
    the {{FilePropertyBag/lastModified}} member could be a {{Date}} object [[ECMA-262]].

4. Return a new {{File}} object |F| such that:
  2. |F| refers to the |bytes| <a>byte</a> sequence.
  3. |F|.{{Blob/size}} is set to the number of total bytes in |bytes|.
  4. |F|.{{File/name}} is set to |n|.
  5. |F|.{{Blob/type}} is set to |t|.
  6. |F|.{{File/lastModified}} is set to |d|.

</div>

### Constructor Parameters ### {#file-constructor-params}

The {{File()}} constructor can be invoked with the parameters below:

<dl>
  <dt>A <dfn id="dfn-fileBits" argument for="File/File(fileBits, fileName, options)"><code>fileBits</code></dfn> <code>sequence</code>
  <dd>which takes any number of the following elements, and in any order:
    * {{BufferSource}} elements.
    * {{Blob}} elements, which includes {{File}} elements.
    * {{USVString}} elements.

  <dt>A <dfn id="dfn-fileName" argument for="File/File(fileBits, fileName, options)"><code>fileName</code></dfn> parameter
  <dd>A {{USVString}} parameter representing the name of the file;
    normative conditions for this constructor parameter can be found in [[#file-constructor]].

  <dt id="def-Properties">An optional {{FilePropertyBag}} dictionary
  <dd>which in addition to the <a href="#dfn-BlobPropertyBagMembers">members</a> of
    {{BlobPropertyBag}} takes one member:
    * An optional <dfn dict-member for=FilePropertyBag id="dfn-FPdate">lastModified</dfn> member,
      which must be a <code>long long</code>;
      normative conditions for this member are provided in [[#file-constructor]].
</dl>

## Attributes ## {#file-attrs}

<dl dfn-type=attribute dfn-for=File>
  <dt><dfn id="dfn-name">name</dfn>
  <dd>The name of the file.
    On getting, this must return the name of the file as a string.
    There are numerous file name variations and conventions used by different underlying OS file systems;
    this is merely the name of the file, without path information.
    On getting, if user agents cannot make this information available,
    they must return the empty string.
    If a {{File}} object is created using a constructor,
    further normative conditions for this attribute are found in [[#file-constructor]].

  <dt><dfn id="dfn-lastModified">lastModified</dfn>
  <dd>The last modified date of the file.
    On getting, if user agents can make this information available,
    this must return a <code>long long</code> set to the time the file was last modified
    as the number of milliseconds since the <a>Unix Epoch</a>.
    If the last modification date and time are not known,
    the attribute must return the current date and time
    as a <code>long long</code> representing the number of milliseconds since the <a>Unix Epoch</a>;
    this is equivalent to <code class="lang-javascript">Date.now()</code> [[ECMA-262]].
    If a {{File}} object is created using a constructor,
    further normative conditions for this attribute are found in [[#file-constructor]].
</dl>

The {{File}} interface is available on objects that expose an attribute of type {{FileList}};
these objects are defined in HTML [[HTML]].
The {{File}} interface, which inherits from {{Blob}}, is immutable,
and thus represents file data that can be read into memory at the time a <a>read operation</a> is initiated.
User agents must process reads on files that no longer exist at the time of read as <a lt="file read error">errors</a>,
throwing a {{NotFoundError}} exception
if using a {{FileReaderSync}} on a Web Worker [[Workers]]
or firing an {{error!!event}} event
with the {{error!!attribute}} attribute returning a {{NotFoundError}}.

<div class="example">
  In the examples below, metadata from a file object is displayed meaningfully, and a file object is created with a name and a last modified date.

  <pre class="lang-javascript">
  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})

  ...
  </pre>
</div>

# The FileList Interface # {#filelist-section}

Note: The {{FileList}} interface should be considered "at risk"
since the general trend on the Web Platform is to replace such interfaces
with the {{Array}} platform object in ECMAScript [[ECMA-262]].
In particular, this means syntax of the sort <code class="lang-javascript">filelist.item(0)</code> is at risk;
most other programmatic use of {{FileList}} is unlikely to be affected by the eventual migration to an {{Array}} type.

This interface is a list of {{File}} objects.

<pre class="idl">
[Exposed=(Window,Worker), Serializable]
interface FileList {
  getter File? item(unsigned long index);
  readonly attribute unsigned long length;
};
</pre>

{{FileList}} objects are [=serializable objects=]. Their [=serialization steps=],
given |value| and |serialized|, are:

1. Set |serialized|.\[[Files]] to an empty [=list=].

2. For each |file| in |value|, append the [=sub-serialization=] of |file| to
   |serialized|.\[[Files]].

Their [=deserialization step=], given |serialized| and |value|, are:

1. [=list/For each=] |file| of |serialized|.\[[Files]], add the [=sub-deserialization=] of |file| to |value|.

<div class="example">
  Sample usage typically involves DOM access to the <code>&lt;input type="file"></code> element within a form,
  and then accessing selected files.

  <pre class="lang-javascript">
    // 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
    }
  </pre>
</div>

## Attributes ## {#attributes-filelist}

  <dl>
    <dt><dfn attribute for=FileList id="dfn-length">length</dfn>
    <dd>must return the number of files in the {{FileList}} object.
      If there are no files, this attribute must return 0.
  </dl>

## Methods and Parameters ## {#filelist-methods-params}

<dl>
  <dt><dfn method for=FileList id="dfn-item">item(index)</dfn>
  <dd>must return the |index|th {{File}} object in the {{FileList}}.
    If there is no |index|th {{File}} object in the {{FileList}},
    then this method must return <code>null</code>.

    <dfn argument for="FileList/item(index)" id="dfn-index">index</dfn> must be treated by user agents
    as value for the position of a {{File}} object in the {{FileList}},
    with 0 representing the first file.
    <a>Supported property indices</a> are the numbers in the range zero
    to one less than the number of {{File}} objects represented by the {{FileList}} object.
    If there are no such {{File}} objects,
    then there are no supported property indices.
</dl>

Note: The {{HTMLInputElement}} interface has a readonly attribute of type {{FileList}},
which is what is being accessed in the above example.
Other interfaces with a readonly attribute of type {{FileList}} include the {{DataTransfer}} interface.


# Reading Data # {#reading-data-section}

## The File Reading Task Source ## {#blobreader-task-source}

This specification defines a new generic [=task source=] called the
<dfn id="fileReadingTaskSource">file reading task source</dfn>,
which is used for all [=queue a task|tasks that are queued=] in this specification
to read byte sequences associated with {{Blob}} and {{File}} objects.
It is to be used for features that trigger in response to asynchronously reading binary data.

## The {{FileReader}} API ## {#APIASynch}

<pre class="idl">
[Exposed=(Window,Worker)]
interface FileReader: EventTarget {
  constructor();
  // async read methods
  void readAsArrayBuffer(Blob blob);
  void readAsBinaryString(Blob blob);
  void readAsText(Blob blob, optional DOMString encoding);
  void readAsDataURL(Blob blob);

  void 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;
};
</pre>

A {{FileReader}} has an associated <dfn for=FileReader>state</dfn>,
that is `"empty"`, `"loading"`, or `"done"`. It is initially `"empty"`.

A {{FileReader}} has an associated <dfn for=FileReader>result</dfn>
(`null`, a {{DOMString}} or an {{ArrayBuffer}}). It is initially `null`.

A {{FileReader}} has an associated <dfn for=FileReader>error</dfn>
(`null` or a {{DOMException}}). It is initially `null`.

The <dfn constructor for=FileReader id=filereaderConstrctr>FileReader()</dfn> constructor,
when invoked, must return a new {{FileReader}} object.

The <dfn attribute for=FileReader>readyState</dfn> attribute's getter,
when invoked, switches on the [=context object=]'s [=FileReader/state=]
and runs the associated step:

: `"empty"`
:: Return {{EMPTY}}
: `"loading"`
:: Return {{LOADING}}
: `"done"`
:: Return {{DONE}}

The <dfn attribute for=FileReader>result</dfn> attribute's getter,
when invoked, must return the [=context object=]'s [=FileReader/result=].

The <dfn attribute for=FileReader>error</dfn> attribute's getter,
when invoked, must return the [=context object=]'s [=FileReader/error=].

<div algorithm="read operation">
A {{FileReader}} |fr| has an associated <dfn id=readOperation>read operation</dfn> algorithm,
which given |blob|, a |type| and an optional |encodingName|,
runs the following steps:

1. If |fr|'s [=FileReader/state=] is `"loading"`,
   throw an {{InvalidStateError}} {{DOMException}}.
1. Set |fr|'s [=FileReader/state=] to `"loading"`.
1. Set |fr|'s [=FileReader/result=] to `null`.
1. Set |fr|'s [=FileReader/error=] to `null`.
1. Let |stream| be the result of calling [=get stream=] on |blob|.
1. Let |reader| be the result of [=get a reader|getting a reader=] from |stream|.
1. Let |bytes| by an empty [=byte sequence=].
1. Let |chunkPromise| be the result of [=read a chunk|reading a chunk=] from |stream| with |reader|.
1. Let |isFirstChunk| be true.
1. [=In parallel=], while true:
  1. Wait for |chunkPromise| to be fulfilled or rejected.
  1. If |chunkPromise| is fulfilled, and |isFirstChunk| is true,
     [=queue a task=] to [=fire a progress event=] called {{loadstart}} at |fr|.

     Issue(119): We might change {{loadstart}} to be dispatched synchronously,
     to align with XMLHttpRequest behavior.

  1. Set |isFirstChunk| to false.

  1. If |chunkPromise| is fulfilled with an object whose `done` property is false and whose `value`
     property is a `Uint8Array` object, run these steps:
    1. Let |bs| be the [=byte sequence=] represented by the `Uint8Array` object.
    1. Append |bs| to |bytes|.
    1. If roughly 50ms have passed since these steps were last invoked,
       [=queue a task=] to [=fire a progress event=] called {{progress}} at |fr|.
    1. Set |chunkPromise| to the result of [=read a chunk|reading a chunk=] from |stream| with |reader|.

  1. Otherwise, if |chunkPromise| is fulfilled with an object whose `done` property is true,
     [=queue a task=] to run the following steps and abort this algorithm:
    1. Set |fr|'s [=FileReader/state=] to `"done"`.
    1. Let |result| be the result of
       [=package data=] given |bytes|, |type|, |blob|'s {{Blob/type}}, and |encodingName|.
    1. If [=package data=] threw an exception |error|:
      1. Set |fr|'s [=FileReader/error=] to |error|.
      1. [=Fire a progress event=] called {{error!!event}} at |fr|.
    1. Else:
      1. Set |fr|'s [=FileReader/result=] to |result|.
      1. [=Fire a progress event=] called {{load}} at the |fr|.
    1. If |fr|'s [=FileReader/state=] is not `"loading"`,
       [=fire a progress event=] called {{loadend}} at the |fr|.

       Note: Event handler for the {{load}} or {{error!!event}} events could have started another load,
       if that happens the {{loadend}} event for this load is not fired.

  1. Otherwise, if |chunkPromise| is rejected with an error |error|,
     [=queue a task=] to run the following steps and abort this algorithm:
    1. Set |fr|'s [=FileReader/state=] to `"done"`.
    1. Set |fr|'s [=FileReader/error=] to |error|.
    1. [=Fire a progress event=] called {{error!!event}} at |fr|.
    1. If |fr|'s [=FileReader/state=] is not `"loading"`,
       [=fire a progress event=] called {{loadend}} at |fr|.

       Note: Event handler for the {{error!!event}} event could have started another load,
       if that happens the {{loadend}} event for this load is not fired.

Use the [=file reading task source=] for all these tasks.
</div>

### Event Handler Content Attributes ### {#event-handler-attributes-section}

The following are the <a>event handler content attributes</a>
(and their corresponding <a>event handler event types</a>)
that user agents must support on {{FileReader}} as DOM attributes:

<table>
  <thead>
    <tr>
      <th><a>event handler content attribute</a>
      <th><a>event handler event type</a>
  <tbody dfn-type=attribute dfn-for=FileReader>
    <tr>
      <td><dfn id="dfn-onloadstart">onloadstart</dfn>
      <td>{{loadstart}}
    <tr>
      <td><dfn id="dfn-onprogress">onprogress</dfn>
      <td>{{progress}}
    <tr>
      <td><dfn id="dfn-onabort">onabort</dfn>
      <td>{{abort}}
    <tr>
      <td><dfn id="dfn-onerror">onerror</dfn>
      <td>{{error!!event}}
    <tr>
      <td><dfn id="dfn-onload">onload</dfn>
      <td>{{load}}
    <tr>
      <td><dfn id="dfn-onloadend">onloadend</dfn>
      <td>{{loadend}}
</table>

### FileReader States ### {#blobreader-state}

<div class="note domintro">
The {{FileReader}} object can be in one of 3 states.
The {{FileReader/readyState}} attribute tells you in which state the object is:

: {{EMPTY}} (numeric value 0)
:: The {{FileReader}} object has been constructed,
   and there are no pending reads.
   None of the [=read methods=] have been called.
   This is the default state of a newly minted {{FileReader}} object,
   until one of the [=read methods=] have been called on it.
: {{LOADING}} (numeric value 1)
:: A {{File}} or {{Blob}} is being read.
   One of the [=read methods=] is being processed,
   and no error has occurred during the read.
: {{DONE}} (numeric value 2)
:: The entire {{File}} or {{Blob}} has been read into memory,
   OR a [=file read error=] occurred,
   OR the read was aborted using {{FileReader/abort()}}.
   The {{FileReader}} is no longer reading a {{File}} or {{Blob}}.
   If {{FileReader/readyState}} is set to {{FileReader/DONE}}
   it means at least one of the [=read methods=] have been called on this {{FileReader}}.

</div>

### Reading a File or Blob ### {#reading-a-file}

The {{FileReader}} interface makes available several <dfn id="asynchronous-read-methods" lt="asynchronous read method">asynchronous read methods</dfn>--
{{FileReader/readAsArrayBuffer()}}, {{FileReader/readAsBinaryString()}}, {{FileReader/readAsText()}} and {{FileReader/readAsDataURL()}},
which read files into memory.

Note: If multiple concurrent read methods are called on the same {{FileReader}} object,
user agents throw an {{InvalidStateError}} on any of the read methods that occur
when {{FileReader/readyState}} = {{FileReader/LOADING}}.

({{FileReaderSync}} makes available several [=synchronous read methods=].
  Collectively, the sync and async read methods of {{FileReader}} and {{FileReaderSync}}
  are referred to as just <dfn lt="read method">read methods</dfn>.)

#### The {{FileReader/readAsDataURL()}} method #### {#readAsDataURL}

The <dfn method for=FileReader id="dfn-readAsDataURL">readAsDataURL(|blob|)</dfn> method,
when invoked, must initiate a [=read operation=] for |blob| with *DataURL*.

#### The {{FileReader/readAsText()}} method #### {#readAsDataText}

The <dfn method for=FileReader id="dfn-readAsText">readAsText(|blob|, |encoding|)</dfn> method,
when invoked, must initiate a [=read operation=] for |blob| with *Text* and |encoding|.

#### The {{FileReader/readAsArrayBuffer()}} #### {#readAsArrayBuffer}

The <dfn method for=FileReader id="dfn-readAsArrayBuffer">readAsArrayBuffer(|blob|)</dfn> method,
when invoked, must initiate a [=read operation=] for |blob| with *ArrayBuffer*.

#### The {{FileReader/readAsBinaryString()}} method #### {#readAsBinaryString}

The <dfn method for=FileReader id="dfn-readAsBinaryString">readAsBinaryString(|blob|)</dfn> method,
when invoked, must initiate a [=read operation=] for |blob| with *BinaryString*.

Note: The use of {{FileReader/readAsArrayBuffer()}} is preferred over
{{FileReader/readAsBinaryString()}}, which is provided for backwards
compatibility.

#### The {{FileReader/abort()}} method #### {#abort}

When the <dfn method for=FileReader id="dfn-abort">abort()</dfn> method is called,
the user agent must run the steps below:

1. If [=context object=]'s [=FileReader/state=] is `"empty"`
   or if [=context object=]'s [=FileReader/state=] is `"done"`
   set [=context object=]'s [=FileReader/result=] to `null`
   and [=terminate this algorithm=].
1. If [=context object=]'s [=FileReader/state=] is `"loading"`
   set [=context object=]'s [=FileReader/state=] to `"done"`
   and set [=context object=]'s [=FileReader/result=] to `null`.
1. If there are any [=tasks=] from the [=context object=]
   on the [=file reading task source=] in an affiliated [=queue a task|task queue=],
   then remove those [=tasks=] from that task queue.
1. [=terminate an algorithm|Terminate the algorithm=] for the [=read method=] being processed.
1. [=Fire a progress event=] called {{abort}} at the [=context object=].
1. If [=context object=]'s [=FileReader/state=] is not `"loading"`,
   [=fire a progress event=] called {{loadend}} at the [=context object=].

## Packaging data ## {#packaging-data}

<div algorithm="package data">
A {{Blob}} has an associated <dfn for=Blob>package data</dfn> algorithm,
given |bytes|, a |type|, a optional |mimeType|, and a optional |encodingName|,
which switches on |type| and runs the associated steps:

: DataURL
:: Return |bytes| as a DataURL [[!RFC2397]] subject to the considerations below:

  * Use |mimeType| as part of the Data URL if it is available
    in keeping with the Data URL specification [[!RFC2397]].
  * If |mimeType| is not available return a Data URL without a media-type. [[!RFC2397]].

  Issue(104): Better specify how the DataURL is generated.

: Text
:: 1. Let |encoding| be failure.
   1. If the |encodingName| is present, set |encoding| to the result of
      [=getting an encoding=] from |encodingName|.
   1. If |encoding| is failure, and |mimeType| is present:
     1. Let |type| be the result of [=parse a MIME type=] given |mimeType|.
     1. If |type| is not failure,
        set |encoding| to the result of [=getting an encoding=]
        from |type|'s [=MIME type/parameters=][`"charset"`].

      <div class="example">
        If `blob` has a {{Blob/type}} attribute of `text/plain;charset=utf-8`
        then <a>getting an encoding</a> is run using `"utf-8"` as the label.
        Note that user agents must parse and extract the portion of the Charset Parameter
        that constitutes a *label* of an encoding.
      </div>
   1. If |encoding| is failure, then set |encoding| to [=UTF-8=].
   1. [=Decode=] |bytes| using fallback encoding |encoding|, and return the result.

: ArrayBuffer
:: Return a new `ArrayBuffer` whose contents are |bytes|.

: BinaryString
:: Return |bytes| as a binary string,
   in which every byte is represented by a code unit of equal value [0..255].

</div>

## Events ## {#events}

The {{FileReader}} object must be the event target for all events in this specification.

When this specification says to <dfn>fire a progress event</dfn> <i>called e</i>
(for some {{ProgressEvent}} <code>e</code>
at a given {{FileReader}} <code>reader</code> as the <a>context object</a>),
the following are normative:

* The progress event <code>e</code> does not bubble.  <code>e.bubbles</code> must be false [[DOM]]
* The progress event <code>e</code> is NOT cancelable. <code>e.cancelable</code> must be false [[DOM]]

### Event Summary ### {#event-summary}

The following are the events that are <a lt="fire an event">fired</a> at {{FileReader}} objects.

<table id="event-summary-table">
  <thead>
    <tr>
      <th>Event name
      <th>Interface
      <th>Fired when…
  <tbody dfn-type="event" dfn-for="FileReader">
    <tr>
      <td><dfn id="dfn-loadstart-event">loadstart</dfn>
      <td>{{ProgressEvent}}
      <td>When the read starts.
    <tr>
      <td><dfn id="dfn-progress-event">progress</dfn>
      <td>{{ProgressEvent}}
      <td>While reading (and decoding) <code>blob</code>
    <tr>
      <td><dfn id="dfn-abort-event">abort</dfn>
      <td>{{ProgressEvent}}
      <td>When the read has been aborted.
        For instance, by invoking the {{FileReader/abort()}} method.
    <tr>
      <td><dfn id="dfn-error-event">error</dfn>
      <td>{{ProgressEvent}}
      <td>When the read has failed (see <a>file read errors</a>).
    <tr>
      <td><dfn id="dfn-load-event">load</dfn>
      <td>{{ProgressEvent}}
      <td>When the read has successfully completed.
    <tr>
      <td><dfn id="dfn-loadend-event">loadend</dfn>
      <td>{{ProgressEvent}}
      <td>When the request has completed (either in success or failure).
</table>

### Summary of Event Invariants ### {#eventInvariants}

*This section is informative.*

The following are invariants applicable to <a lt="fire an event">event firing</a>
for a given asynchronous <a>read method</a> in this specification:

1. Once a {{loadstart}} has been fired,
  a corresponding {{loadend}} fires at completion of the read,
  UNLESS any of the following are true:

  * the <a>read method</a> has been cancelled using {{FileReader/abort()}}
    and a new <a>read method</a> has been invoked
  * the event handler function for a {{load}} event initiates a new read
  * the event handler function for a {{error!!event}} event initiates a new read.

  Note: The events {{loadstart}} and {{loadend}} are not coupled in a one-to-one manner.

  <div class="example">
    This example showcases "read-chaining":
    initiating another read from within an event handler while the "first" read continues processing.

    <pre class="lang-javascript">
      // 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
    </pre>
  </div>
2. One {{progress}} event will fire when <code>blob</code> has been completely read into memory.
3. No {{progress}} event fires before {{loadstart}}.
4. No {{progress}} event fires after any one of {{abort}}, {{load}}, and {{error!!event}} have fired.
  At most one of {{abort}}, {{load}}, and {{error!!event}} fire for a given read.
5. No {{abort}}, {{load}}, or {{error!!event}} event fires after {{loadend}}.

## Reading on Threads ## {#readingOnThreads}

Web Workers allow for the use of synchronous {{File}} or {{Blob}} read APIs,
since such reads on threads do not block the main thread.
This section defines a synchronous API, which can be used within Workers [[Web Workers]].
Workers can avail of both the asynchronous API (the {{FileReader}} object)
*and* the synchronous API (the {{FileReaderSync}} object).

### The {{FileReaderSync}} API ### {#FileReaderSync}

This interface  provides methods to <dfn id="read-method-sync" lt="synchronous read method">synchronously read</dfn>
{{File}} or {{Blob}} objects into memory.

<pre class="idl">
[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);
};
</pre>

#### Constructors #### {#filereadersyncConstrctr}

When the {{FileReaderSync()}} constructor is invoked,
the user agent must return a new {{FileReaderSync}} object.

#### The {{FileReaderSync/readAsText()}} #### {#readAsTextSync}

The <dfn method for=FileReaderSync id="dfn-readAsTextSync">readAsText(|blob|, |encoding|)</dfn> method,
when invoked, must run these steps:

1. Let |stream| be the result of calling [=get stream=] on |blob|.
1. Let |reader| be the result of [=get a reader|getting a reader=] from |stream|.
1. Let |promise| be the result of [=read all bytes|reading all bytes=] from |stream| with |reader|.
1. Wait for |promise| to be fulfilled or rejected.
1. If |promise| fulfilled with a [=byte sequence=] |bytes|:
  1. Return the result of [=package data=] given |bytes|, *Text*, |blob|'s {{Blob/type}}, and |encoding|.
1. Throw |promise|'s rejection reason.

#### The {{FileReaderSync/readAsDataURL()}} method #### {#readAsDataURLSync-section}

The <dfn method for=FileReaderSync id="dfn-readAsDataURLSync">readAsDataURL(|blob|)</dfn> method,
when invoked, must run these steps:

1. Let |stream| be the result of calling [=get stream=] on |blob|.
1. Let |reader| be the result of [=get a reader|getting a reader=] from |stream|.
1. Let |promise| be the result of [=read all bytes|reading all bytes=] from |stream| with |reader|.
1. Wait for |promise| to be fulfilled or rejected.
1. If |promise| fulfilled with a [=byte sequence=] |bytes|:
  1. Return the result of [=package data=] given |bytes|, *DataURL*, and |blob|'s {{Blob/type}}.
1. Throw |promise|'s rejection reason.

#### The {{FileReaderSync/readAsArrayBuffer()}} method #### {#readAsArrayBufferSyncSection}

The <dfn method for=FileReaderSync id="dfn-readAsArrayBufferSync">readAsArrayBuffer(|blob|)</dfn> method,
when invoked, must run these steps:

1. Let |stream| be the result of calling [=get stream=] on |blob|.
1. Let |reader| be the result of [=get a reader|getting a reader=] from |stream|.
1. Let |promise| be the result of [=read all bytes|reading all bytes=] from |stream| with |reader|.
1. Wait for |promise| to be fulfilled or rejected.
1. If |promise| fulfilled with a [=byte sequence=] |bytes|:
  1. Return the result of [=package data=] given |bytes|, *ArrayBuffer*, and |blob|'s {{Blob/type}}.
1. Throw |promise|'s rejection reason.

#### The {{FileReaderSync/readAsBinaryString()}} method #### {#readAsBinaryStringSyncSection}

The <dfn method for=FileReaderSync id="dfn-readAsBinaryStringSync">readAsBinaryString(|blob|)</dfn> method,
when invoked, must run these steps:

1. Let |stream| be the result of calling [=get stream=] on |blob|.
1. Let |reader| be the result of [=get a reader|getting a reader=] from |stream|.
1. Let |promise| be the result of [=read all bytes|reading all bytes=] from |stream| with |reader|.
1. Wait for |promise| to be fulfilled or rejected.
1. If |promise| fulfilled with a [=byte sequence=] |bytes|:
  1. Return the result of [=package data=] given |bytes|, *BinaryString*, and |blob|'s {{Blob/type}}.
1. Throw |promise|'s rejection reason.

Note: The use of {{FileReaderSync/readAsArrayBuffer()}} is preferred over
{{FileReaderSync/readAsBinaryString()}}, which is provided for
backwards compatibility.

# Errors and Exceptions # {#ErrorAndException}

<dfn lt="file read error" id="file-error-read">File read errors</dfn> can occur when reading files from the underlying filesystem.
The list below of potential error conditions is *informative*.

* The {{File}} or {{Blob}} being accessed may not exist
  at the time one of the <a>asynchronous read methods</a> or <a>synchronous read methods</a> are called.
  This may be due to it having been moved or deleted after a reference to it was acquired
  (e.g. concurrent modification with another application).
  See {{NotFoundError}}.
* A {{File}} or {{Blob}} may be unreadable.
  This may be due to permission problems that occur after a reference to a {{File}} or {{Blob}} has been acquired
  (e.g. concurrent lock with another application).
  Additionally, the <a>snapshot state</a> may have changed.
  See {{NotReadableError}}.
* User agents MAY determine that some files are unsafe for use within Web applications.
  A file may change on disk since the original file selection,
  thus resulting in an invalid read.
  Additionally, some file and directory structures may be considered restricted by the underlying filesystem;
  attempts to read from them may be considered a security violation.
  See [[#security-discussion]] and {{SecurityError}}.

## Throwing an Exception or Returning an Error ## {#dfn-error-codes}

*This section is normative.*

Error conditions can arise when reading a {{File}} or a {{Blob}}.

The <a>read operation</a> can terminate due to error conditions when reading a {{File}} or a {{Blob}};
the particular error condition that causes the [=get stream=] algorithm to fail
is called a <dfn id="failureReason">failure reason</dfn>. A <a>failure reason</a> is one of
[=NotFound=], [=UnsafeFile=], [=TooManyReads=], [=SnapshotState=], or [=FileLock=].

Synchronous read methods <a>throw</a> exceptions of the type in the table below
if there has been an error owing to a particular <a>failure reason</a>.

Asynchronous read methods use the {{FileReader/error!!attribute}} attribute of the {{FileReader}} object,
which must return a {{DOMException}} object of the most appropriate type from the table below
if there has been an error owing to a particular <a>failure reason</a>,
or otherwise return null.

<table class='data'>
  <thead>
    <tr>
      <th>Type
      <th>Description and Failure Reason
  <tbody>
    <tr>
      <td>{{NotFoundError}}
      <td>If the {{File}} or {{Blob}} resource could not be found at the time the read was processed,
        this is the <dfn id="NotFoundFR">NotFound</dfn> <a>failure reason</a>.

        For asynchronous read methods the {{error!!attribute}} attribute must return a {{NotFoundError}} exception
        and synchronous read methods must <a>throw</a> a {{NotFoundError}} exception.
    <tr>
      <td>{{SecurityError}}
      <td>If:
        * it is determined that certain files are unsafe for access within a Web application, this is the <dfn id="UnsafeFileFR">UnsafeFile</dfn> <a>failure reason</a>.
        * it is determined that too many read calls are being made on {{File}} or {{Blob}} resources, this is the <dfn id="TooManyReadsFR">TooManyReads</dfn> <a>failure reason</a>.

        For asynchronous read methods the {{error!!attribute}} attribute may return a {{SecurityError}} exception
        and synchronous read methods may <a>throw</a> a {{SecurityError}} exception.

        This is a security error to be used in situations not covered by any other <a>failure reason</a>.
    <tr>
      <td>{{NotReadableError}}
      <td>If:
        * the <a>snapshot state</a> of a {{File}} or a {{Blob}} does not match the state of the underlying storage,
          this is the <dfn id="SnapshotStateFR">SnapshotState</dfn> <a>failure reason</a>.
        * the {{File}} or {{Blob}} cannot be read,
          typically due due to permission problems that occur after a <a>snapshot state</a> has been established
          (e.g. concurrent lock on the underlying storage with another application)
          then this is the <dfn id="FileLockFR">FileLock</dfn> <a>failure reason</a>.

        For asynchronous read methods the {{error!!attribute}} attribute must return a {{NotReadableError}} exception
        and synchronous read methods must <a>throw</a> a {{NotReadableError}} exception.
</table>

# A URL for Blob and MediaSource reference # {#url}

This section defines a [=url/scheme=] for a [=/URL=] used to refer to {{Blob}}
and {{MediaSource}} objects.

## Introduction ## {#url-intro}

*This section is informative.*

[=Blob URL|Blob (or object) URLs=] are URLs like
`blob:http://example.com/550e8400-e29b-41d4-a716-446655440000`.
This enables integration of {{Blob}}s and {{MediaSource}}s with other
APIs that are only designed to be used with URLs, such as the <{img}> element.
[=Blob URLs=] can also be used to navigate to as well as to trigger downloads
of locally generated data.

For this purpose two static methods are exposed on the {{URL}} interface,
{{URL/createObjectURL(obj)}} and {{URL/revokeObjectURL(url)}}.
The first method creates a mapping from a [=/URL=] to a {{Blob}},
and the second method revokes said mapping.
As long as the mapping exist the {{Blob}} can't be garbage collected,
so some care must be taken to revoke the URL as soon as the reference is no longer needed.
All URLs are revoked when the global that created the URL itself goes away.

## Model ## {#url-model}

Each user agent must maintain a <dfn id="BlobURLStore" export>blob URL store</dfn>.
A [=blob URL store=] is a [=map=]
where [=map/keys=] are [=valid URL strings=]
and [=map/values=] are [=blob URL Entries=].

A <dfn export>blob URL entry</dfn> consists of
an <dfn export for="blob URL entry">object</dfn> (of type {{Blob}} or {{MediaSource}}),
and an <dfn export for="blob URL entry">environment</dfn> (an [=environment settings object=]).

[=map/Keys=] in the [=blob URL store=] (also known as <dfn lt="blob URL|object URL" export>blob URLs</dfn>)
are [=valid URL strings=] that when [=URL parser|parsed=]
result in a [=/URL=] with a [=url/scheme=] equal to "`blob`",
an [=empty host=], and a [=url/path=] consisting of one element itself also a [=valid URL string=].

<div algorithm="createBlobURL">
To <dfn id="unicodeBlobURL" lt="generate a new blob URL|generating a new blob URL">
generate a new blob URL</dfn>, run the following steps:

1. Let |result| be the empty string.
1. Append the string "`blob:`" to |result|.
1. Let |settings| be the [=current settings object=]
1. Let |origin| be |settings|'s [=environment settings object/origin=].
1. Let |serialized| be the <a lt="ASCII serialization of an origin">ASCII serialization</a> of |origin|.
1. If |serialized| is "`null`", set it to an implementation-defined value.
1. Append |serialized| to |result|.
1. Append U+0024 SOLIDUS (`/`) to |result|.
1. Generate a UUID [[!RFC4122]] as a string and append it to |result|.
1. Return |result|.

</div>

<div class="example">
  An example of a blob URL that can be generated by this algorithm is
  `blob:https://example.org/9115d58c-bcda-ff47-86e5-083e9a215304`1.
</div>

<div algorithm="addBlobURL">
To <dfn id="add-an-entry" lt="add an entry|add the entry|add an entry to the blob URL store|add the entry to the blob URL store|adding an entry to the blob URL store" for="blob url store">
add an entry to the blob URL store</dfn> for a given |object|,
run the following steps:

1. Let |store| be the user agent's [=blob URL store=].
1. Let |url| be the result of [=generating a new blob URL=].
1. Let |entry| be a new [=blob URL entry=] consisting of |object| and the [=current settings object=].
1. [=map/Set=] |store|[|url|] to |entry|.
1. Return |url|.

</div>

<div algorithm="removeBlobURL">
To <dfn id="removeTheEntry" lt="remove an entry|remove the entry|remove an entry from the blob URL store|remove the entry from the blob URL store" for="blob url store">
remove an entry from the blob URL store</dfn> for a given |url|,
run the following steps:

1. Let |store| be the user agent's [=blob URL store=];
1. Let |url string| be the result of [=URL serializer|serializing=] |url|.
1. [=map/Remove=] |store|[|url string|].

</div>

## Dereferencing Model for blob URLs ## {#requestResponseModel}

<div algorithm="resolveURL">
To <dfn export for="blob URL" lt="resolve">resolve a blob URL</dfn> given a |url| (a [=URL=]), run the following steps:

1. [=Assert=]: |url|'s [=url/scheme=] is "`blob`".
1. Let |store| be the user agent's [=blob URL store=].
1. Let |url string| be the result of [=URL serializer|serializing=] |url| with the *exclude fragment flag* set.
1. If |store|[|url string|] [=map/exists=], return |store|[|url string|]; otherwise return failure.

</div>

Futher requirements for the parsing and fetching model for [=blob URLs=] are defined in the [[!URL]] and [[!Fetch]] specifications.

### Origin of blob URLs ### {#originOfBlobURL}

*This section is informative.*

The origin of a blob URL is always the same as that of the environment that created the URL,
as long as the URL hasn't been revoked yet. This is achieved by the [[URL]] spec looking up
the URL in the [=blob URL store=] when parsing a URL, and using that entry to return
the correct origin.

If the URL was revoked the serialization of the origin will still remain the same
as the serialization of the origin of the environment that created the blob URL,
but for opaque origins the origin itself might be distinct. This difference isn't
observable though, since a revoked blob URL can't be resolved/fetched anymore anyway.

<h4 id="lifeTime" dfn for="blob url" lt="lifetime|lifetime stipulation" export>Lifetime of blob URLs</h4>

This specification extends the [=unloading document cleanup steps=] with the following steps:

1. Let |environment| be the {{Document}}'s [=relevant settings object=].
1. Let |store| be the user agent's [=blob URL store=];
1. Remove from |store| any entries for which the [=map/value=]'s [=blob URL entry/environment=] is equal to |environment|.

Issue: This needs a similar hook when a worker is unloaded.

## Creating and Revoking a blob URL ## {#creating-revoking}

<a>Blob URLs</a> are created and revoked using static methods exposed on the {{URL}} object.
Revocation of a <a>blob URL</a> decouples the <a>blob URL</a> from the resource it refers to,
and if it is dereferenced after it is revoked,
user agents must act as if a <a>network error</a> has occurred.
This section describes a supplemental interface to the URL specification [[URL]]
and presents methods for <a>blob URL</a> creation and revocation.

<pre class="idl">
[Exposed=(Window,DedicatedWorker,SharedWorker)]
partial interface URL {
  static DOMString createObjectURL((Blob or MediaSource) obj);
  static void revokeObjectURL(DOMString url);
};
</pre>

<div algorithm="createObjectURL">
The <dfn method for=URL id="dfn-createObjectURL">createObjectURL(|obj|)</dfn> static method must
return the result of [=adding an entry to the blob URL store=] for |obj|.
</div>

<div algorithm="revokeObjectURL">
The <dfn method for=URL id="dfn-revokeObjectURL">revokeObjectURL(|url|)</dfn> static method must run these steps:

1. Let |url record| be the result of [=URL parser|parsing=] |url|.
1. If |url record|'s [=url/scheme=] is not "`blob`", return.
1. Let |origin| be the [=url/origin=] of |url record|.
1. Let |settings| be the [=current settings object=].
1. If |origin| is not [=same origin=] with |settings|'s [=environment settings object/origin=], return.
1. [=Remove an entry from the Blob URL Store=] for |url|.

Note: This means that rather than throwing some kind of error, attempting to revoke a URL that isn't registered will silently fail.
User agents might display a message on the error console if this happens.

Note: Attempts to dereference |url| after it has been revoked will result in a [=network error=].
Requests that were started before the |url| was revoked should still succeed.
</div>

<div class="example">
  In the example below,
  <code>window1</code> and <code>window2</code> are separate,
  but in the <a>same origin</a>;
  <code>window2</code> could be an <{iframe}> inside <code>window1</code>.

  <pre class="lang-javascript">
    myurl = window1.URL.createObjectURL(myblob);
    window2.URL.revokeObjectURL(myurl);
  </pre>

  Since a user agent has one global [=blob URL store=],
  it is possible to revoke an object URL from a different window than from which it was created.
  The <code>URL.{{revokeObjectURL()}}</code> call
  ensures that subsequent dereferencing of <code>myurl</code>
  results in a the user agent acting as if a <a>network error</a> has occurred.
</div>

### Examples of blob URL Creation and Revocation ### {#examplesOfCreationRevocation}

<a>Blob URL</a>s are strings that are used to [=/fetch=] {{Blob}} objects,
and can persist for as long as the <code>document</code> from which they were minted
using <code>URL.{{createObjectURL()}}</code>--
see [[#lifeTime]].

This section gives sample usage of creation and revocation of <a>blob URL</a>s with explanations.

<div class="example">
  In the example below, two <{img}> elements [[HTML]] refer to the same <a>blob URL</a>:

  <pre class="lang-javascript">
    url = URL.createObjectURL(blob);
    img1.src = url;
    img2.src = url;
  </pre>
</div>

<div class="example">
  In the example below,  <code>URL.{{revokeObjectURL()}}</code> is explicitly called.

  <pre class="lang-javascript">
    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);
    }
  </pre>
</div>

The example above allows multiple references to a single <a>blob URL</a>,
and the web developer then revokes the <a>blob URL</a> string after both image objects have been loaded.
While not restricting number of uses of the <a>blob URL</a> offers more flexibility,
it increases the likelihood of leaks;
developers should pair it with a corresponding call to <code>URL.{{revokeObjectURL()}}</code>.

# Security and Privacy Considerations # {#security-discussion}

*This section is informative.*

This specification allows web content to read files from the underlying file system,
as well as provides a means for files to be accessed by unique identifiers,
and as such is subject to some security considerations.
This specification also assumes that the primary user interaction is with the <code>&lt;input type="file"/></code> element of HTML forms [[HTML]],
and that all files that are being read by {{FileReader}} objects have first been selected by the user.
Important security considerations include preventing malicious file selection attacks (selection looping),
preventing access to system-sensitive files,
and guarding against modifications of files on disk after a selection has taken place.

: Preventing selection looping
:: During file selection, a user may be bombarded with the file picker associated with <code>&lt;input type="file"/></code>
   (in a "must choose" loop that forces selection before the file picker is dismissed)
   and a user agent may prevent file access to any selections by making the  {{FileList}} object returned be of size 0.
: System-sensitive files
:: (e.g. files in /usr/bin, password files, and other native operating system executables)
   typically should not be exposed to web content,
   and should not be accessed via <a>blob URLs</a>.
   User agents may <a>throw</a> a {{SecurityError}} exception for synchronous read methods,
   or return a {{SecurityError}} exception for asynchronous reads.

Issue: This section is provisional; more security data may supplement this in subsequent drafts.

# Requirements and Use Cases # {#requirements}

This section covers what the requirements are for this API,
as well as illustrates some use cases.
This version of the API does not satisfy all use cases;
subsequent versions may elect to address these.

* Once a user has given permission,
  user agents should provide the ability to read and parse data directly from a local file programmatically.

  <div class="example">
    A lyrics viewer.
    User wants to read song lyrics from songs in his plist file.
    User browses for plist file.
    File is opened, read, parsed, and presented to the user as a sortable, actionable list within a web application.
    User can select songs to fetch lyrics.
    User uses the "browse for file" dialog.
  </div>
* Data should be able to be stored locally so that it is available for later use,
  which is useful for offline data access for web applications.

  <div class="example">
    A Calendar App.
    User's company has a calendar.
    User wants to sync local events to company calendar,
    marked as "busy" slots (without leaking personal info).
    User browses for file and selects it.
    The <code>text/calendar</code> file is parsed in the browser,
    allowing the user to merge the files to one calendar view.
    The user wants to then save the file back to his local calendar file (using "Save As"?).
    The user can also send the integrated calendar file back to the server calendar store asynchronously.
  </div>
* User agents should provide the ability to save a local file programmatically given an amount of data and a file name.

  Note: While this specification doesn't provide an explicit API call to trigger downloads,
  the HTML5 specification has addressed this.
  The <{a/download}> attribute of the <{a}> element initiates a download,
  saving a {{File}} with the name specified.
  The combination of this API and the <{a/download}> attribute on <{a}> elements
  allows for the creation of files within web applications,
  and the ability to save them locally.

  <div class="example">
    A Spreadsheet App.
    User interacts with a form, and generates some input.
    The form then generates a CSV (Comma Separated Variables) output for the user to import into a spreadsheet,
    and uses "Save...".
    The generated output can also be directly integrated into a web-based spreadsheet,
    and uploaded asynchronously.
  </div>
* User agents should provide a streamlined programmatic ability to send data from a file to a remote server
  that works more efficiently than form-based uploads today.

  <div class="example">
    A Video/Photo Upload App.
    User is able to select large files for upload,
    which can then be "chunk-transfered" to the server.
  </div>
* User agents should provide an API exposed to script that exposes the features above.
  The user is notified by UI anytime interaction with the file system takes place,
  giving the user full ability to cancel or abort the transaction.
  The user is notified of any file selections,
  and can cancel these.
  No invocations to these APIs occur silently without user intervention.

<h2 id="acknowledgements-section" class="no-num">
Acknowledgements</h2>

This specification was originally developed by the SVG Working Group. Many thanks to Mark Baker and Anne van Kesteren for their feedback.

Thanks to Robin Berjon, Jonas Sicking and Vsevolod Shmyroff for editing the original specification.

Special thanks to Olli Pettay, Nikunj Mehta, Garrett Smith, Aaron Boodman, Michael Nordman, Jian Li, Dmitry Titov, Ian Hickson, Darin Fisher, Sam Weinig, Adrian Bateman and Julian Reschke.

Thanks to the W3C WebApps WG, and to participants on the public-webapps@w3.org listserv
