Ajax Binary Response
Asked Answered
O

6

17

Hi I'm wondering if there's anyway to stream a binary response in AJAX? This would be an ultimate solution otherwise I would need to realize the binary image to a file then stream that file to the user with a different URL.

new Ajax.Request('/viewImage?id=123', {
  // request returns a binary image inputstream
  onSuccess: function(transport) {
      // text example
      // alert(transport.responseText)

      // QUESTION: is there a streaming binary response?
      $('imgElem').src = transport.responseBinary;
  },
  onFailure: function(transport) {
      // handle failure
  }
});
Outage answered 29/10, 2009 at 18:59 Comment(0)
T
24

It might not be possible to stream binary data, but you can use Ajax to retrieve binary data.

This is possible using one of two methods: Javascript Typed Arrays or an XMLHttpResponse overrideMimeType hack. Have a read of a good article on MDN – these examples are taken from there: Sending and Receiving Binary Data

The Typed Array method looks like this:

var oReq = new XMLHttpRequest();
oReq.open("GET", "/myfile.png", true);
oReq.responseType = "arraybuffer";

oReq.onload = function (oEvent) {
  var arrayBuffer = oReq.response; // Note: not oReq.responseText
  if (arrayBuffer) {
    var byteArray = new Uint8Array(arrayBuffer);
    for (var i = 0; i < byteArray.byteLength; i++) {
      // do something with each byte in the array
    }
  }
};

oReq.send(null);

Typed Arrays are not supported in IE < 10, Firefox < 4, Chrome < 7, Safari < 5.1 and Opera < 11.6, and mobile support is shaky but improving.

The second method uses an XMLHttpRequest method called overrideMimeType to allow the binary data to be passed through unmodified.

var req = new XMLHttpRequest();
req.open('GET', '/myfile.png', false);
// XHR binary charset opt by Marcus Granado 2006 [http://mgran.blogspot.com]
req.overrideMimeType('text\/plain; charset=x-user-defined');
req.send(null);
if (req.status != 200) return '';
// do stuff with req.responseText;

You get an unparsed binary string, upon which you can use var byte = filestream.charCodeAt(x) & 0xff; to retrieve a specific byte.

Telium answered 18/5, 2012 at 4:19 Comment(1)
why 'text\/plain; charset=x-user-defined' and not e.g. 'text\/plain\;\ charset\=x\-user\-defined' or 'text/plain; charset=x-user-defined' ? :)Chastain
L
7

This is an extension to Tom Ashworth's response (which helped to put me on the right track with the issue I was facing). This allows you to just get the filestream (FileStreamResult if you are using asp.net mvc) and set it to the img src, which is cool.

var oReq = new XMLHttpRequest();
oReq.open("post", '/somelocation/getmypic', true );        
oReq.responseType = "blob";
oReq.onload = function ( oEvent )
{
    var blob = oReq.response;
    var imgSrc = URL.createObjectURL( blob );                        
    var $img = $( '<img/>', {                
        "alt": "test image",
        "src": imgSrc
    } ).appendTo( $( '#bb_theImageContainer' ) );
    window.URL.revokeObjectURL( imgSrc );
};
oReq.send( null );

The basic idea is that the data is returned untampered with, it is placed in a blob and then a url is created to that object in memory. See here and here. Note supported browsers.

Lithia answered 30/10, 2013 at 11:35 Comment(0)
R
5

What you can do, if you are trying to generate an image on the fly, is to just do:

<img src="http://myurl/myfile.php?id=3" />

then you can send the data with the appropriate mimetype.

If you really want to send an image, then you may want to look at the HTML5 canvas tag, but I am not certain how excanvas would work with this, for being cross-platform.

You could write to the canvas, but it would be more efficient to just use the img tag.

Ragamuffin answered 29/10, 2009 at 19:5 Comment(0)
W
2

When you call your service, you should ask for a dataType: 'binary' response. Then, you can use saveAs(FileSaver.js) to trigger the download or createObjectURL to open in new window.

But, $.ajax doesn't let you download binary content out of the box, it will try to decode your binary from UTF-8 and corrupt it. Either use a jQuery plugin to solve this problem jquery.binarytransport.js

exemplo:

$.ajax({
    type: "POST",
    url: $("form#data").attr("action"),
    data: formData,
    dataType: 'binary',     //--> using jquery.binarytransport.js
    success: function (response) {
        // Default response type is blob
        
        saveAs(response, "test.pdf"); //--> using FileSaver.js

        let fileURL = URL.createObjectURL(blob);
        window.open(fileURL);        // open file in new window
    }
});

Good look! :)

Wallack answered 26/5, 2021 at 9:46 Comment(0)
U
1

You can send any response you want, being it plain text, HTML, an image... whatever! It's up to you how to handle it when you receive it.

But... you cannot assign a binary image to the <IMG> src attribute. You'd better just return the URL to the image and assign that instead - well, to be honest, there are some encodings to embed images in the SRC, but they are not cross-browser so you'll want to stay away from them.

Unity answered 29/10, 2009 at 19:2 Comment(0)
S
1

I managed to get download of binary file without corrupted data working using jQuery ajax by adding:

xhrFields: {responseType: 'blob'}

Superabound answered 19/7, 2022 at 15:12 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.