Ajax Binary Response
Привет, мне интересно, есть ли способ передать двоичный ответ в AJAX? Это было бы окончательным решением, в противном случае мне нужно было бы реализовать двоичное изображение в файл, а затем передать этот файл пользователю с другим 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
}
});
6 ответов
Это может быть невозможно для потоковой передачи двоичных данных, но вы можете использовать Ajax для извлечения двоичных данных.
Это возможно, используя один из двух методов: Javascript Typed Arrays или XMLHttpResponse overrideMimeType hack. Прочитайте хорошую статью о MDN - эти примеры взяты оттуда: Отправка и получение двоичных данных
Метод Typed Array выглядит следующим образом:
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);
Типизированные массивы не поддерживаются в IE < 10, Firefox < 4, Chrome < 7, Safari < 5.1 и Opera < 11.6, а поддержка мобильных устройств шатка, но улучшается.
Второй метод использует метод XMLHttpRequest с именем overrideMimeType, чтобы разрешить передачу двоичных данных без изменений.
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;
Вы получаете непарсированную двоичную строку, на которой вы можете использовать var byte = filestream.charCodeAt(x) & 0xff;
получить определенный байт.
Это продолжение ответа Тома Эшворта (который помог мне встать на правильный путь с проблемой, с которой я столкнулся). Это позволяет вам просто получить файловый поток (FileStreamResult, если вы используете asp.net mvc) и установить его в img src, что круто.
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 );
Основная идея заключается в том, что данные возвращаются без изменений, они помещаются в большой двоичный объект, а затем создается URL для этого объекта в памяти. Смотрите здесь и здесь. Обратите внимание на поддерживаемые браузеры.
Что вы можете сделать, если вы пытаетесь создать изображение на лету, это просто сделать:
<img src="http://myurl/myfile.php?id=3" />
Затем вы можете отправить данные с соответствующим MIME-тип.
Если вы действительно хотите отправить изображение, вы можете посмотреть на тег HTML5 canvas, но я не уверен, как с этим будет работать excanvas, потому что он кроссплатформенный.
Вы можете написать на холст, но было бы более эффективно просто использовать тег img.
Когда вы звоните в свою службу, вы должны попросить
dataType: 'binary'
отклик. Затем вы можете использовать
saveAs
(FileSaver.js) для запуска загрузки или createObjectURL для открытия в новом окне.
Но $ .ajax не позволяет загружать двоичный контент из коробки, он попытается декодировать ваш двоичный файл из UTF-8 и повредить его. Либо используйте плагин jQuery для решения этой проблемы jquery.binarytransport.js
пример:
$.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
}
});
Молодец! :)
Вы можете отправить любой желаемый ответ, будь то обычный текст, HTML, изображение... что угодно! Вам решать, как справиться с этим, когда вы его получите.
Но... вы не можете назначить двоичное изображение <IMG>
атрибут src. Лучше просто вернуть URL-адрес изображения и назначить его вместо этого - ну, если честно, есть некоторые кодировки для встраивания изображений в SRC, но они не являются кросс-браузерными, поэтому вы захотите держаться от них подальше,
Мне удалось загрузить двоичный файл без поврежденных данных, работающих с использованием jQuery ajax, добавив:
xhrFields: {responseType: 'blob'}