Copyright © 2013 W3C® (MIT, ERCIM, Keio, Beihang), All Rights Reserved. W3C liability, trademark and document use rules apply.
This specification provides an API for representing binary data in web applications as a Stream
object,
as well as programmatically building and reading its contents. This includes:
Stream
interface, which represents a sequence of data that can be read over time.StreamReader
interface, which provides methods to read the contents of a Stream
as a
Blob
, DataURL
, ArrayBuffer
, or as Text
.StreamBuilder
interface, which allows for creating a new Stream
whose contents is read from an internal buffer that was made by appending Text
, Blobs
, or ArrayBuffers
.Stream
.Stream
.
Additionally, this specification defines objects to be used within threaded web applications for the synchronous reading of a Stream
.
This API is designed to be used in conjunction with other APIs and elements on the web platform, notably:
File [FILE-API],
XMLHttpRequest
(e.g. with an overloaded send()
method
and response
object for Stream
objects) [XMLHTTPREQUEST2],
postMessage
, and
Web Workers [WEBWORKERS].
This section describes the status of this document at the time of its publication. Other documents may supersede this document. A list of current W3C publications and the latest revision of this technical report can be found in the W3C technical reports index at http://www.w3.org/TR/.
This document was published as a First Public Working Draft by the W3C Web Applications (WebApps) as a Working Draft. This document is intended to become a W3C Recommendation. If you wish to make comments regarding this document, please send them to public-webapps@w3.org (subscribe, archives). All comments are welcome.
Publication as a Working Draft does not imply endorsement by the W3C Membership. This is a draft document and may be updated, replaced or obsoleted by other documents at any time. It is inappropriate to cite this document as other than work in progress.
This document was produced by a group operating under the 5 February 2004 W3C Patent Policy. W3C maintains a public list of any patent disclosures made in connection with the deliverables of the group; that page also includes instructions for disclosing a patent. An individual who has actual knowledge of a patent which the individual believes contains Essential Claim(s) must disclose the information in accordance with section 6 of the W3C Patent Policy.
This section is non-normative.
Web applications should have the ability to acquire and manipulate data in a wide variety of forms,
including as a sequence of data made available over time.
This specification defines the basic representation for Streams
,
errors raised by Streams
,
and programmatic ways to read and create Streams
.
The Stream
interface represents binary data which can be obtained over time. A Stream
can come from APIs
such as XMLHttpRequest
, or can
be built using StreamBuilder
.
The StreamReader
interface represents a way to read data
from a Stream
as a Blob
, DataURL
, ArrayBuffer
, or as Text
,
and should happen asynchronously on the user agent’s main thread,
with an optional synchronous API used within threaded web applications.
An asynchronous API for reading Streams
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 Stream
,
which is closely based on the FileReader interface defined in the [FILE-API].
A StreamReader
object provides asynchronous read methods to access the Stream's
data as a
Blob
, DataURL
, ArrayBuffer
, or as Text
through event handler 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 long Stream
reads or high latency network requests)
and error conditions that may arise during reading of a Stream
. An example will be illustrative.
In the example below, different code blocks handle progress, error, and success conditions.
The example demonstrates how to read a Stream
using StreamReader
.
function startRead(stream) { var reader = new StreamReader(); // Handle progress, success, and errors reader.onprogress = updateProgress; reader.onload = loaded; reader.onerror = errorHandler; // Read the first 1024 bytes of the stream as UTF-8 reader.readAsText(stream, "UTF-8", 1024); } function updateProgress(evt) { var bytesLoaded = (evt.loaded / 1024); // Increase bytes loaded counter } function loaded(evt) { // Obtain the read stream data var streamRead = evt.target.result; } function errorHandler(evt) { if(evt.target.error.name == "NOT_READABLE_ERR") { // The stream could not be read } }
In the example below, different code blocks handle progress, error, and success conditions.
The example below demonstrates how to obtain a Stream
from XMLHttpRequest
to begin playing a large video in readystate
3.
function handler() { if(this.readyState == this.LOADING) { var theStream = this.response; var streamURL = URL.createObjectURL(theStream); document.getElementById("myVideoTag").src = streamURL; } } var client = new XMLHttpRequest(); client.onreadystatechange = handler; client.setRequestHeader('customHeader', 'value'); client.setRequestHeader('customHeader2', 'value2'); client.open("GET", "myvideo.h264"); client.responseType = "stream"; client.send();
In addition to reading a Stream, this specification introduces a programatic way to build a Stream with the StreamBuilder
interface.
The StreamBuilder
interface represents a way to provide the data to be read from a Stream by appending the data to an internal buffer.
StreamBuilder
supports appending Blob
, ArrayBuffer
, and Text
data to the buffer.
StreamBuilder
also provides an event to notify when the data available to be read from the buffer has fallen below a given threshold.
The example below demonstrates how to use StreamBuilder
to load a stream into the audio tag, whose data is processed and built dynamically at read time.
The thresholdReached
event is fired when the buffer falls below 1024 bytes.
function thresholdReached(){ var moreData = //do work to create more data to place into the stream //if we have no more data to process and place in the stream, we close if(moreData == null){ sbuilder.close(); } else{ sbuiler.append(moreData); } } var sbuilder = new StreamBuilder("audio/mp3", 1024); var sbuilder.onthresholdreached = thresholdReached; var streamURL = URL.createObjectURL(sbuilder.stream); document.getElementById('audioTag').src = streamURL;
This interface represents a raw sequence of linear data which can be read over time.
It provides an attribute representing the type of data represented by the Stream
.
A Stream
is an object that:
Blob
can be used, such as URL.createObjectURL()
interface Stream {
readonly attribute DOMString type;
void close ();
};
type
of type DOMString, readonlyStream
,
expressed as an RFC2046 MIME type [RFC2046].
Conforming user agents should return the MIME type of the Stream
, if it is known.
If conforming user agents cannot determine the media type of the Stream
, they must return the empty string.
A string is a valid MIME type if it matches the media-type token defined in section 3.7 "Media Types" of RFC 2616 [HTTP11].
close
Stream
has been closed, it cannot be used again; dereferencing a Stream URI bound to a Stream object on which close has been called results in a 500 Error.
void
This interface provides methods to read the data of a Stream
using progress events and event handler attributes.
It is desirable to read data from Streams asynchronously in the main thread of user agents.
This interface provides such an asynchronous API, and is specified to be used with the global object
(Window [HTML5]).
The StreamReader
is designed in a way to closely follow the W3C FileReader [FILE-API],
and thus only identifies changes or additions to the way FileReader methods behave.
When the StreamReader()
constructor is invoked, the user agent must return a new StreamReader
object.
In environments where the global object is represented by a Window
or a WorkerGlobalScope
object,
the StreamReader
constructor must be available.
For event handler attributes, event handlers for StreamReader
should mimic
6.4.3 Event Handler Attributes of the File API specification. [FILE-API]
For states, event handlers for StreamReader
should mimic 6.4.4 FileReader States
of the File API specification, except as defined below for DONE
(numeric value of 2). [FILE-API]
Multiple reads on StreamReader
should mimic
6.4.5.1 Multiple Reads of the File API specification. [FILE-API]
interface StreamReader : EventTarget {
void readAsBlob (Stream
stream, unsigned long long maxSize);
void readAsArrayBuffer (Stream
stream, optional unsigned long long maxSize);
void readAsText (Stream
stream, optional DOMString encoding, optional unsigned long long maxSize);
void readAsDataURL (Stream
Stream, optional unsigned long long maxSize);
void abort ();
const unsigned short EMPTY = 0;
const unsigned short LOADING = 1;
const unsigned short DONE = 2;
readonly attribute unsigned short readyState;
readonly attribute any result;
readonly attribute StreamError error;
attribute Function onloadstart;
attribute Function onprogress;
attribute Function onload;
attribute Function onabort;
attribute Function onerror;
attribute Function onloadend;
};
error
of type StreamError, readonlyonabort
of type FunctionFileReader.onabort
event handler.
onerror
of type FunctionFileReader.onerror
event handler.
onload
of type FunctionFileReader.onload
event handler.
onloadend
of type FunctionFileReader.onloadend
event handler.
onloadstart
of type FunctionFileReader.onloadstart
event handler.
onprogress
of type FunctionFileReader.onprogress
event handler.
readyState
of type unsigned short, readonlyresult
of type any, readonlyBlob
of the data read from the Stream
with the type property set as the type of the Stream
.
abort
FileReader.abort()
. [FILE-API]void
readAsArrayBuffer
This method should mimic FileReader.readAsArrayBuffer()
. [FILE-API]
The only addition is the addition of a maxSize
parameter, which has the following adjustment:
maxSize
is less than one, throw an Invalid Argument exception. Terminate these overall steps.
maxSize
has been reached,
set readyState
to DONE
.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
stream |
| ✘ | ✘ | The Stream to be read |
maxSize | unsigned long long | ✘ | ✔ | The maximum number of bytes to be read before completion |
void
readAsBlob
When this method is called, the user agent must run the steps below (unless otherwise indicated).
maxSize
is less than one, through an Invalid Argument exception. Terminate these overall steps.
readyState
is LOADING
, raise a NOT_ALLOWED_ERR
exception and terminate these steps.
stream
parameter,
set readyState
to DONE
and set
result
to null
.
Proceed to the error steps below.
error
.
Set the error
attribute;
on getting, the error
attribute must be a StreamError
object with a valid error code
that indicates the kind of file error that has occurred.
loadend
.
readyState
to LOADING
.
loadstart
.
Stream
:
maxSize
parameter has been set,
set the readyState
to DONE
when the number of bytes read reaches MAX_SIZE
or the stream has been fully read and the number of bytes is less than MAX_SIZE
.
readyState
to DONE
when the stream has been fully read.
result
attribute to be stream’s data content represented as a Blob
;
on getting, the result result
returns the (complete) data of stream as a Blob
.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
stream |
| ✘ | ✘ | The Stream to be read |
maxSize | unsigned long long | ✘ | ✘ | The maximum number of bytes to be read before completion |
void
readAsDataURL
This method should mimic FileReader.readAsDataURL()
. [FILE-API]
The only addition is the addition of a maxSize
parameter, which has the following adjustment.
maxSize
is less than one, through an Invalid Argument exception. Terminate these overall steps.
result
attribute
with the Stream
as a DataURL [RFC2397] after the stream has been fully read,
or the number of bytes specified by maxSize
has been reached;
on getting, the result
attribute
returns the (complete) data of stream as a DataURL [RFC2397].
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
Stream |
| ✘ | ✘ | The Stream to be read |
maxSize | unsigned long long | ✘ | ✔ | The maximum number of bytes to be read before completionk |
void
readAsText
This method should mimic FileReader.readAsText()
. [FILE-API]
The only addition is the addition of a maxSize
parameter, which has the following adjustment:
maxSize
is less than one, through an Invalid Argument exception. Terminate these overall steps.
maxSize
is specified, continue reading until the stream has been completed.
maxSize
has been reached,
set readyState
to DONE
.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
stream |
| ✘ | ✘ | The Stream to be read |
encoding | DOMString | ✘ | ✔ | The encoding format |
maxSize | unsigned long long | ✘ | ✔ | The maximum number of bytes to be read before completion |
void
DONE
of type unsigned shortabort()
. The StreamReader
is no longer reading a Stream
.
EMPTY
of type unsigned shortEMPTY
state of the
FileReader States
LOADING
of type unsigned shortLOADING
state of the
FileReader States
StreamReader
implements EventTarget;
All instances of the
type are defined to also implement the EventTarget interface.StreamReader
The following are the event handler attributes (and their corresponding event handler event types) that user agents must support on StreamReader as DOM attributes:
event handler attribute | event handler event type |
---|---|
onloadstart |
loadstart |
onprogress |
progress |
onload |
load |
onabort |
abort |
onerror |
error |
onloadend |
loadend |
The following are the events that are fired at
objects;
firing events is defined in DOM Level 3 Events [DOM-LEVEL-3-EVENTS],
and the table below is normative for the events in this specification.
StreamReader
Event name | Interface | Fired when… |
---|---|---|
loadstart |
ProgressEvent |
When the read starts. |
progress |
ProgressEvent |
While reading (and decoding) a stream , and reporting progress.
|
abort |
ProgressEvent |
When the read has been aborted. For instance, by invoking the abort() method. |
error |
ProgressEvent |
When the read has failed (see errors). |
load |
ProgressEvent |
When the read has successfully completed. |
loadend |
ProgressEvent |
When the request has completed (either in success or failure). |
This interface provides methods to read the data of a Stream
.
When the StreamReaderSync()
constructor is invoked, the user agent must return a new StreamReaderSync
object.
In environments where the global object is represented by a WorkerGlobalScope
object,
the StreamReaderSync
constructor must be available.
interface StreamReaderSync {
Blob readAsBlob (Stream
stream, optional unsigned long long maxSize);
ArrayBuffer readAsArrayBuffer (Stream
stream, optional unsigned long long maxSize);
DOMString readAsText (Stream
stream, optional DOMString encoding, optional unsigned long long maxSize);
DOMString readAsDataURL (Stream
stream, optional unsigned long long maxSize);
};
readAsArrayBuffer
This method should mimic FileReader.readAsArrayBuffer()
. [FILE-API]
The only addition is the addition of a maxSize
parameter that affects the amount of bytes to read from the Stream
.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
stream |
| ✘ | ✘ | The Stream to be read |
maxSize | unsigned long long | ✘ | ✔ | The maximum number of bytes to be read before completion |
ArrayBuffer
readAsBlob
When this method is called, the following steps must be followed:
stream
parameter,
throw a StreamException
with the appropriate error code.
Terminate these overall steps.
stream
until the end is reached,
or the number of bytes specified by maxSize
have been read.
Return the data contents of stream
as a blob
with the type
property set as the type of the Stream
.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
stream |
| ✘ | ✘ | The Stream to be read |
maxSize | unsigned long long | ✘ | ✔ | The maximum number of bytes to be read before completion |
Blob
readAsDataURL
This method should mimic FileReader.readAsDataURL()
. [FILE-API]
The only addition is the addition of a maxSize
parameter that affects the amount of the amount of bytes to read from the Stream
.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
stream |
| ✘ | ✘ | The Stream to be read |
maxSize | unsigned long long | ✘ | ✔ | The maximum number of bytes to be read before completion |
DOMString
readAsText
This method should mimic FileReader.readAsText()
. [FILE-API]
The only addition is the addition of a maxSize
parameter that affects the amount of the amount of bytes to read from the Stream
.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
stream |
| ✘ | ✘ | The Stream to be read |
encoding | DOMString | ✘ | ✔ | The encoding format |
maxSize | unsigned long long | ✘ | ✔ | The maximum number of bytes to be read before completion |
DOMString
StreamReader will read a Stream until maxSize has been reached or the Stream has no further data to return. If a Stream has been read until the end, then there is no further data to return. Subsequent read calls will return the following:
readAsBlob
Blob
with size zeroreadAsArrayBuffer
ArrayBuffer
with length zeroreadAsText
readAsDataURL
This interface should mimic the FileError
Interface, and contain the same error codes.
This interface should mimic the FileException
Interface, , and contain the same error codes.
The StreamBuilder
interface provides a way for developers to create a Stream
by appending data. During a read on the stream
from a StreamBuilder
, the data is read 'First in, First out',
in the order it was appended. StreamBuilder
provides methods for appending different data, as well as a thresholdreached
event to be notified when the amount of data available for read has fallen below a specified threshold.
When the StreamBuilder(in contentType)
constructor is invoked, the user agent must return a new StreamBuilder
object.
If the StreamBuilder(in contentType)
constructor is invoked with the optional thresholdLimit
overload,
then this limit will be used to fire the thresholdreached
event.
In environments where the global object is represented by a WorkerGlobalScope
object,
the StreamBuilder()
constructor must be available.
[Constructor, Constructor(DOMString contentType, optional int thresholdLimit)]
interface StreamBuilder : EventTarget {
void append (String data);
void append (Blob data);
void append (ArrayBuffer data);
void close ();
readonly attribute Stream
stream;
readonly attribute unsigned long long availableDataSize;
attribute Function onthresholdreached;
};
availableDataSize
of type unsigned long long, readonlyonthresholdreached
of type Functionthresholdreached
events.
stream
of type Stream
, readonlyStream
represented by the StreamBuilder
.append
Appends the supplied text to the data available for the Stream
, writing it as UTF-8.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
data | String | ✘ | ✘ | The data to append |
void
append
Appends the supplied Blob
to the data available for the Stream
.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
data | Blob | ✘ | ✘ | The data to append |
void
append
Appends the supplied ArrayBuffer
to the data available for the Stream
.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
data | ArrayBuffer | ✘ | ✘ | The data to append |
void
close
Stream
. This is done by returning on the next and subsequent reads with no data.void
When a read on a stream from StreamBuilder
is made, the following steps must be followed:
availableDataSize
.
Stream
has been closed, return all the data available,
and set availableDataSize
to zero.availableDataSize
fell below the thresholdLimit
value specified in the constructor,
fire an event called thresholdreached
.
The following are the event handler attributes (and their corresponding event handler event types) that user agents must support on StreamBuilder
as DOM attributes:
event handler attribute | event handler event type |
---|---|
onthresholdreached |
thresholdreached |
The following are the events that are fired at
objects;
firing events is defined in DOM Level 3 Events [DOM-LEVEL-3-EVENTS],
and the table below is normative for the events in this specification.
StreamBuilder
Event name | Interface | Fired when… |
---|---|---|
thresholdreached |
StreamBuilder |
The availableDataSize has fallen below the thresholdLimit value specified in the constructor |
To reference a Stream
, the same URI used for Blobs
and Files
in
6.7. A URI for Blob and File reference of
the File API spec should be used. [FILE-API]
The definitions of Origin, Lifetime, Referencing, and Dereferencing of a Blob
should be applied to a Stream
.
A Stream URI is a Blob URI
that is referencing a Stream
.
These URIs are created and revoked using methods exposed on the URL object,
as defined in 6.7.5. Creating and Revoking a Blob URI
of the File API spec. [FILE-API]
URL.createObjectURL and URL.revokeObjectURL should both be extended as follows:
interface URL {
static DOMString createObjectURL (any object);
static void revokeObjectURL (DOMString url);
};
createObjectURL
, staticThe extension onto createObjectURL
should have the following steps added.
Blob
or Stream
argument
that is not valid, then the user agent must return null.Blob
or Stream
argument,
user agents must return a unique Blob URI
that can be used to dereference the blob
or stream
argument.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
object | any | ✘ | ✘ |
DOMString
revokeObjectURL
, static
The extension onto revokeObjectURL
should have the following steps added.
Blob
or Stream
that is both
valid and in the same origin of the global object’s URL
property on which this static method was called,
user agents must return a 404 response code when the URL is dereferenced.Blob
or Stream
that is not valid
or if the value provided for the URL argument is not a Blob URI
or if the URL argument refers to a Blob
or Stream
that is not in the same origin
as the global object’s URL
property, this method call does nothing.
User agents may display a message on their error console.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
url | DOMString | ✘ | ✘ |
void
A Stream
should have the same security considerations as a Blob
.
This is outlined in 6.8. Security Considerations
of the File API specification. [FILE-API]
Because a Stream
uses a Blob URI
, cross origin requests on a Stream
will not be supported.
This specification proposes an extension to XMLHttpRequest
[XMLHTTPREQUEST2] to add support for Stream
. This section is temporary and is meant to provide a recommendation for how Stream
should be incorporated into XMLHttpRequest
.
This will extend XMLHttpRequest
to allow for receiving and uploading of a Stream
.
One such scenario is providing access to data during readyState
3 (loading).
The sections below document in detail what extensions must be done to XMLHttpRequest
to support Stream
.
A responseType of ‘stream
’ should be introduced to XMLHttpRequest
.
Section 4.7.7 the responseType
attribute
in XMLHttpRequest Level 2 [XMLHTTPREQUEST2] should now read:
On setting the responseType
attribute these steps must be run:
OPENED
or
HEADERS_RECEIVED
raise an INVALID_STATE_ERR
exception and terminate these steps.
arraybuffer
", "blob
",
"document
", "stream
", or "text
" terminate these steps.responseType
attribute's value to the given value.
Section 4.7.8 the response
attribute
in XMLHttpRequest Level 2 [XMLHTTPREQUEST2] should now read:
The response
attribute must return the result of running these steps:
responseType
is the empty string or "text"responseType
is “stream
”responseType
is "arraybuffer
"responseType
is "blob
"responseType
is "document
"
A stream
is binary data obtained sequentially over time.
Given this, a Stream
should be accessible in readyState
3 (LOADING).
Section 4.7.5 Response Entity Body in XMLHttpRequest Level 2 [XMLHTTPREQUEST2] should have the following additions:
The stream response entity body is a Stream
representing the response entity body.
If the stream response entity body has no value assigned to it let it be the return value of the following algorithm:
Stream
object and terminate these steps.
Stream
object representing the
response entity body.
Section 4.6.6 The send()
method
in XMLHttpRequest Level 2 [XMLHTTPREQUEST2] should have the following additions:
Stream
If the object's type
attribute is not the empty string let mime type be its value.
Let the request entity body be the raw data represented by data.
The Stream
type allows for completion of several end-to-end experiences. This section covers what the requirements are for this API, and
illustrates some use cases.
XMLHttpRequest
in readyState
3
Videos can typically be large files that may take a long time to download, and require authentication or certain headers to access. For certain video formats, an application can begin playing the video once the first chunks of data are available, and would not need to wait for the entire video to download.
StreamReader
as it is being read via XMLHttpRequest
If a file format is understood, then an application can make sense of the data as it being made available. For example, a given file may be very large and the application wants to begin processing the data immediately, rather than having to wait for full download of the file.
StreamBuilder
and XMLHttpRequest
There are situations where an application may have data to upload once the application is processing. This could involve processing of data an application wants to upload as it is being created. One such case is the upload of GPS coordinates within an application. The coordiantes may constantly change, and the application wants to upload the data as it being collected.
Stream
and XMLHttpRequest
Media streaming scenarios require the ability to quickly receive data over the network and connect it to a media element. An application can successfully accomplish this by receiving a Stream in readyState
3 and assign it to a media element. This helps avoid the application from having to buffer the data prior to assigning it to a media element.
Thanks to Eliot Graff for editorial assistance. Special thanks to the W3C.