Ajax Binary Response

21,130

Solution 1

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.

Solution 2

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.

Solution 3

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.

Solution 4

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! :)

Solution 5

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.

Share:
21,130
dev101
Author by

dev101

U.S. Army Korea Defense Vet, Senior Software Engr, Java, Android, Spring Framework &amp; IntelliJ Enthusiast. Loves Travel, My MBP Retina, My Wife, and My Pug Lucy. LinkedIn https://www.linkedin.com/feed/

Updated on May 26, 2021

Comments

  • dev101
    dev101 almost 3 years

    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
      }
    });