Возникла задача ― загрузить с сервера XLSX
-файл. Запрос ― POST
. Файл, понятное дело, бинарный
. На проекте уже подключена jQuery
, и, первым делом, я решил воспользоваться её стандартным $.ajax
. Сколько не бился ― так и не удалось получить blob
-результат от запроса. Использовать же решение через iframe
-ы и form
-ы тоже не хотелось. Во-первых уж больно костыльно (привет 90-ые). во-вторых нужно будет ещё чудить с передачей параметров POST-запроса (content-type: json
). Гуглил-гуглил, но ни одного вменяемого решения (которое не стыдно было бы утащить в проект) я так и не нашёл. Но, т.к. интересует поддержка только последних версий современных браузеров, удалось найти и применить более изящное и функциональное решение. Итак…
- Забудем про
jQuery
и воспользуемся нативнымXMLHttpRequest
-ом - Указав ему
responseType = ‘blob’
.< - Получившийся результат (
blob
) загоняем вURL.createObjectURL
. - В результате получим псевдо-URL ссылку, начинающуюся с “
blob:
”.
Ну а дальше уже по-желанию. Я генерирую новый <a/>-тег
, задаю ему нужные аттрибуты download
и href
(та самая blob-ссылка
), вызываю у ссылки .click()
. Апосля ссылку удаляю. Проверял в Firefox
-е и Chrome
-е.
Небольшая заготовка:
function loadBlob(params, data) { return new Promise((resolve, reject) => { const xhr = _.assign(new XMLHttpRequest(), { onload(){ resolve(xhr.response); }, onerror(e){ reject(e.target.status); } }); xhr.open(params.method || 'POST', params.url); xhr.responseType = 'blob'; const contentType = params.contentType || 'application/json'; xhr.setRequestHeader('content-type', contentType); if(contentType === 'application/json') data = JSON.stringify(data); xhr.send(data); }); }
Ну и загрузка файла:
downloadBlob(blob, fname) { const url = window.URL || window.webkitURL; const object = url.createObjectURL(blob); var $a = $('<a>', { 'href': object, 'download': _.isString(fname) ? fname : 'file.txt' }) .appendTo(document.body); $a[0].click(); $a.remove(); }