Using jQuery AJAX to download a binary file

I am attempting to use jQuery AJAX to download a binary audio file.

Normally I would just issue a command like this:

 windows.location.href = 'http://marksdomain(dot)com/audioFile.wav' ;

However, recently our server has been waiting too long to respond, and I get a nasty gateway timeout message.

It has been suggested that I use jQuery AJAX instead, which makes sense since then i would have more control over the timeout.

Here is the code i have played with so far:

$.ajax({
    url: 'http://marksdomain(dot)com/audioFile.wav',
    timeout: 999999,
    dataType: 'binary',
    processData: false, // this one does not seem to do anything ?

    success: function (result) {
        console.log(result.length);
    },
    error: function (result, errStatus, errorMessage) {
        console.log(errStatus + ' -- ' + errorMessage);
    }
};

When I omit the "dataType", the binary file is coming through about three times larger than it actually is on the server. However, when i make the dataType equal to "binary", AJAX throws an error:

"No conversion from text to binary"

From some earlier posts, it sounds as if jQuery AJAX cannot handle binary files in this manner.

I did discover Delivery.js which actually works quite well for what I am attempting, but I would rather not use a node solution if possible.

Any suggestions?

Answers:

Answer

Just use XHR directly. This example is taken from MDN:

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

oReq.onload = function(oEvent) {
  var arrayBuffer = oReq.response;

  // if you want to access the bytes:
  var byteArray = new Uint8Array(arrayBuffer);
  // ...

  // If you want to use the image in your DOM:
  var blob = new Blob([arrayBuffer], {type: "image/png"});
  var url = URL.createObjectURL(blob);
  someImageElement.src = url;

  // whatever...
};

oReq.send();
Answer

You can set up an $.ajax transport to modify the settings as mentioned here: http://www.henryalgus.com/reading-binary-files-using-jquery-ajax/

// use this transport for "binary" data type

$.ajaxTransport("+binary", function (options, originalOptions, jqXHR) {
    // check for conditions and support for blob / arraybuffer response type
    if (window.FormData && ((options.dataType && (options.dataType == 'binary')) || (options.data && ((window.ArrayBuffer && options.data instanceof ArrayBuffer) || (window.Blob && options.data instanceof Blob))))) {
        return {
            // create new XMLHttpRequest
            send: function (headers, callback) {
                // setup all variables
                var xhr = new XMLHttpRequest(),
                    url = options.url,
                    type = options.type,
                    async = options.async || true,
                    // blob or arraybuffer. Default is blob
                    dataType = options.responseType || "blob",
                    data = options.data || null,
                    username = options.username || null,
                    password = options.password || null;

                xhr.addEventListener('load', function () {
                    var data = {};
                    data[options.dataType] = xhr.response;
                    // make callback and send data
                    callback(xhr.status, xhr.statusText, data, xhr.getAllResponseHeaders());
                });

                xhr.open(type, url, async, username, password);

                // setup custom headers
                for (var i in headers) {
                    xhr.setRequestHeader(i, headers[i]);
                }

                xhr.responseType = dataType;
                xhr.send(data);
            },
            abort: function () {
                jqXHR.abort();
            }
        };
    }
});

and then make your ajax call:

return $.ajax({
    url: url,
    method: 'GET',
    dataType: 'binary',
    processData: 'false',
    responseType: 'arraybuffer',
    headers: { 'X-Requested-With': 'XMLHttpRequest' }
}).then(function (response) {
    var data = new Uint8Array(response);
    //do something with the data
    return data;
}, function (error) {
    alertify.error('There was an error! Error:' + error.name + ':' + error.status)
});
Answer

If you must use jQuery, you can use $.ajaxSetup() to modify low-level settings.

Example:

  // Set up AJAX settings for binary files:
  $.ajaxSetup({
    beforeSend: function (jqXHR, settings) {
      if (settings.dataType === 'binary') {
        settings.xhr().responseType = 'arraybuffer';
      }
    }
  })

  // Make the actual call:
  let result = await $.ajax({
    url: '/api/export/data',
    type: 'GET',
    contentType: 'application/json',
    dataType: 'binary',
    processData: false,
    headers: {
      token: localStorage.token,
    },
  });

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.