Are there any XHR-like browser APIs available for streaming binary to a server over HTTP?
I want to make an HTTP PUT request and create data programmatically, over time. I don't want to create all this data at once, since there could be gigs of it sitting in memory. Some psueudo-code to illustrate what I'm getting at:
var dataGenerator = new DataGenerator(); // Generates 8KB UInt8Array every second
var streamToWriteTo;
http.put('/example', function (requestStream) {
streamToWriteTo = requestStream;
});
dataGenerator.on('data', function (chunk) {
if (!streamToWriteTo) {
return;
}
streamToWriteTo.write(chunk);
});
I currently have a web socket solution in place instead, but would prefer regular HTTP for better interop with some existing server-side code.
EDIT: I can use bleeding edge browser APIs. I was looking at the Fetch API, as it supports ArrayBuffers, DataViews, Files, and such for request bodies. If I could somehow fake out one of these objects so that I could use the Fetch API with dynamic data, that would work for me. I tried creating a Proxy object to see if any methods were called that I could monkey patch. Unfortunately, it seems that the browser (at least in Chrome) is doing the reading in native code and not in JS land. But, please correct me if I'm wrong on that.
I'm currently searching for exactly the same thing (upstreaming via Ajax). What I currently found, looks as if we are searching at the bleeding edge of browser's feature design ;-)
XMLHttpRequest definition tells in step 4 bodyinit that the content extraction of this is (or can be) a readablestream.
I'm still searching (as a non-webdeveloper) for information of how to create such a thing and to feed data into the "other end" of that "readablestream" (which namely should be a "writablestream", but I yet did not find that).
Maybe you are better in searching and can post here if you found a method to implement these design plans.
^5
sven
An approach utilizing
ReadableStream
to stream arbitrary data;RTCDataChannel
to send and, or, receive arbitrary data in form ofUint8Array
;TextEncoder
to create8000
bytes of random data stored in aUint8Array
,TextDecoder
to decodeUint8Array
returned byRTCDataChannel
to string for presentation, note could alternatively useFileReader
.readAsArrayBuffer
and.readAsText
here.The markup and script code were modified from examples at
MDN - WebRTC: Simple RTCDataChannel sample
, includingadapter.js
which containsRTCPeerConnection
helpers; Creating your own readable stream.Note also, example stream is cancelled when total bytes transferred reaches
8000 * 8
:64000
plnkr http://plnkr.co/edit/cln6uxgMZwE2EQCfNXFO?p=preview
I don't know how to do this with pure HTML5 APIs, but one possible workaround is to use a Chrome App as a background service to provide additional features to a web page. If you're already willing to use development browsers and enable experimental features, this seems like just an incremental step further than that.
Chrome Apps can call the
chrome.sockets.tcp
API, on which you can implement any protocol you want, including HTTP and HTTPS. This would provide the flexibility to implement streaming.A regular web page can exchange messages with an App using the
chrome.runtime
API, as long as the App declares this usage. This would allow your web page to make asynchronous calls to your App.I wrote this simple App as a proof of concept:
manifest.json
background.js
This App does not have a user interface. It listens for connections and makes a hard-coded PUT request to
http://httpbin.org/put
(httpbin is a useful test site but note it does not support chunked encoding). The PUT data (currently hard-coded to exactly 17 octets) is streamed in from the client (using as few or as many messages as desired) and sent to the server. The response from the server is streamed back to the client.This is just a proof of concept. A real App should probably:
Here is a sample web page that performs a streaming upload (of 17 octets) using the App as a service (note that you will have to configure your own App id):
When I load this web page in a Chrome browser with the App installed, httpbin returns:
You could use
Promise
,setTimeout
, recursion. See also PUT vs POST in RESTServer-Sent Events and WebSockets are the preferred methods but in your case you are wanting to create a Representational state transfer, REST, API and use Long Polling. See How do I implement basic “Long Polling”?
Long polling process is handled both on the client side and server side. The server script and http server must be configured to support long polling.
Other than long polling, short polling (XHR/AJAX) requires the browser to poll the server.