Использование jQuery ajax для загрузки двоичного файла
Я пытаюсь использовать jQuery ajax для загрузки двоичного аудиофайла.
обычно я бы просто выдал такую команду:
windows.location.href = 'http://marksdomain(dot)com/audioFile.wav' ;
однако в последнее время наш сервер слишком долго ждал ответа, и я получаю неприятное сообщение тайм-аута шлюза.
было предложено использовать jQuery-ajax вместо этого, что имеет смысл, так как с тех пор у меня было бы больше контроля над таймаутом.
вот код, с которым я играл так далеко:
$.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);
}
когда я опускаю "тип данных", двоичный файл проходит примерно в три раза больше, чем на самом деле на сервере. Однако, когда я делаю тип данных равным "двоичному", ajax выдает ошибку:
"No conversion from text to binary"
из некоторых более ранних сообщений звучит так, как будто jquery-ajax не может обрабатывать двоичные файлы таким образом.
я обнаружила доставки.js что на самом деле работает довольно хорошо для того, что я пытаюсь, но я бы предпочел не использовать решение узла, если это возможно.
какие предложения?
3 ответов
просто используйте XHR напрямую. Этот пример взят из 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();
Если вы должны использовать jQuery, вы можете использовать $.ajaxSetup()
для изменения настроек низкого уровня.
пример:
// 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,
},
});
Вы можете установить $.ajax transport для изменения параметров, как указано здесь: 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();
}
};
}
});
а затем сделайте свой вызов 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)
});