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].
closeStream 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.
abortFileReader.abort(). [FILE-API]voidreadAsArrayBuffer
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 |
voidreadAsBlobWhen 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 |
voidreadAsDataURL
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 |
voidreadAsText
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 |
voidDONE 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 |
ArrayBufferreadAsBlobWhen 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 |
BlobreadAsDataURL
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 |
DOMStringreadAsText
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 |
DOMStringStreamReader 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:
readAsBlobBlob with size zeroreadAsArrayBufferArrayBuffer with length zeroreadAsTextreadAsDataURL
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 |
voidappend
Appends the supplied Blob to the data available for the Stream.
| Parameter | Type | Nullable | Optional | Description |
|---|---|---|---|---|
| data | Blob | ✘ | ✘ | The data to append |
voidappend
Appends the supplied ArrayBuffer to the data available for the Stream.
| Parameter | Type | Nullable | Optional | Description |
|---|---|---|---|---|
| data | ArrayBuffer | ✘ | ✘ | The data to append |
voidcloseStream. 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 | ✘ | ✘ |
DOMStringrevokeObjectURL, 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.