misc/class
lib/jquery_pnotify, lib/moment, lib/lodash, misc/notification, site/engine, misc/social
if( $.browser.msie && $.browser.version <= 8 ) include('lib/respond'); $._social.__cfg = {"init":[{"service":"basic"},{"fb_app_id":"1997094873850041","service":"fb"},{"vk_app_id":"2978320","service":"vk"},{"service":"twi"}],"like":[{"service":"fb"},{"service":"vk"},{"via":"","channel":"","hash_tag":"","service":"twi"}]}; window._SiteEngine = new classes.SiteEngine( { user_id: 0, controller: 'content_article', action: 'view', content_css_version: '1459538664', social_enabled: 0} );

Faiwer

Блог web-программиста

Загрузка binary-файла

 — 
28 января 2016 14:00

Возникла задача ― загрузить с сервера XLSX-файл. Запрос ― POST. Файл, понятное дело, бинарный. На проекте уже подключена jQuery, и, первым делом, я решил воспользоваться её стандартным $.ajax. Сколько не бился ― так и не удалось получить blob-результат от запроса. Использовать же решение через iframe-ы и form-ы тоже не хотелось. Во-первых уж больно костыльно (привет 90-ые). во-вторых нужно будет ещё чудить с передачей параметров POST-запроса (content-type: json). Гуглил-гуглил, но ни одного вменяемого решения (которое не стыдно было бы утащить в проект) я так и не нашёл. Но, т.к. интересует поддержка только последних версий современных браузеров, удалось найти и применить более изящное и функциональное решение. Итак…

  1. Забудем про jQuery и воспользуемся нативным XMLHttpRequest-ом
  2. Указав ему responseType = 'blob'.
  3. Получившийся результат (blob) загоняем в URL.createObjectURL.
  4. В результате получим псевдо-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();
}
Теги:
JavaScript
Комментарии
Оставить комментарий
Оставить комментарий:
Отправить через:
Предпросмотр
modules/comment
window._Comment_content_article_124 = new classes.Comment( '#comment_block_content_article_124', { type: 'content_article', node_id: '124', user: 1, user_id: 0, admin: 0, view_time: null, msg: { empty: 'Комментарий пуст', ask_link: 'Ссылка:', ask_img: 'Ссылка на изображение:' } });