web-dev-qa-db-fra.com

Utiliser jquery ajax pour télécharger un fichier binaire

J'essaie d'utiliser jquery ajax pour télécharger un fichier audio binaire. 

Normalement, je voudrais juste émettre une commande comme celle-ci:

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

Cependant, récemment, notre serveur a attendu trop longtemps pour répondre et je reçois un vilain message de délai d'attente de la passerelle.

Il a été suggéré que j'utilise plutôt jquery-ajax, ce qui est logique depuis lors, j'aurais plus de contrôle sur le délai d'attente.

Voici le code avec lequel j'ai joué jusqu'à présent:

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

Lorsque j'oublie le "type de données", le fichier binaire est environ trois fois plus volumineux que sur le serveur. Cependant, lorsque je rends le type de données égal à "binaire", ajax génère une erreur:

"No conversion from text to binary"

D'après certains articles précédents, jquery-ajax ne peut pas gérer les fichiers binaires de cette manière.

J'ai découvert Delivery.js qui fonctionne assez bien pour ce que je tente, mais je préférerais ne pas utiliser de solution de noeud si possible.

Aucune suggestion?

13
edwardsmarkf

Il suffit d'utiliser XHR directement. Cet exemple est tiré de 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();
15
Brandon

Si vous devez utiliser jQuery, vous pouvez utiliser $.ajaxSetup() pour modifier les paramètres de bas niveau.

Exemple:

  // 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,
    },
  });
1
K48

Vous pouvez configurer un transport $ .ajax pour modifier les paramètres comme indiqué ici: 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();
                        }
                    };
                }
            });

et faites ensuite votre appel ajax:

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