Наконец-то я нашел решение, которое удовлетворяет всем моим требованиям и работает в IE11, FF и Chrome (и ухудшает вид OK в Safari ...).
Идея состоит в том, чтобы создать объект Blob
, содержащий данные из ответа, а затем заставить браузер открыть его в виде файла. Он немного отличается для IE (фирменный API) и Chrome/FF (с использованием элемента ссылки).
Вот реализация, как небольшие угловые службы:
myApp.factory('Download', [function() {
return {
openAsFile : function(response){
// parse content type header
var contentTypeStr = response.headers('Content-Type');
var tokens = contentTypeStr.split('/');
var subtype = tokens[1].split(';')[0];
var contentType = {
type : tokens[0],
subtype : subtype
};
// parse content disposition header, attempt to get file name
var contentDispStr = response.headers('Content-Disposition');
var proposedFileName = contentDispStr ? contentDispStr.split('"')[1] : 'data.'+contentType.subtype;
// build blob containing response data
var blob = new Blob([response.data], {type : contentTypeStr});
if (typeof window.navigator.msSaveBlob !== 'undefined'){
// IE : use proprietary API
window.navigator.msSaveBlob(blob, proposedFileName);
}else{
var downloadUrl = URL.createObjectURL(blob);
// build and open link - use HTML5 a[download] attribute to specify filename
var a = document.createElement("a");
// safari doesn't support this yet
if (typeof a.download === 'undefined') {
window.open(downloadUrl);
}
var link = document.createElement('a');
link.href = downloadUrl;
link.download = proposedFileName;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
}
}
}]);
Аргумент ответа ожидает объект $http
ответа. Ниже приведен пример использования с запросом POST:
$http.post(url, {property : 'value'}, {responseType: 'blob'}).then(function(response){
Download.openAsFile(response);
});
Примечание параметр responseType
. Без этого мои CSV-данные считывались как текст и сохранялись в памяти как UTF-8 (или 16), а затем файл сохранялся в той же кодировке, в результате чего Excel не распознавал специальные символы, такие как éè и т. Д. Так как мои CSV предназначены для открытия Excel, сервер кодирует их Windows 1252, я хотел сохранить их таким образом. Установка этого параметра responseType
на blob
достигает этого.
Отказ от ответственности: Он должен работать с любым типом файла. Но я тестировал его только с файлами CSV! Двоичные файлы могут вести себя как-то иначе!
Помогает ли это: http://stackoverflow.com/questions/14551194/how-are-parameters-sent-in-an-http-post-request И можете ли вы опубликовать фрагмент, как сделать JS HTTP-вызов? Если речь идет о диалоговом окне загрузки, вам нужно указать дополнительный заголовок. – Markus
Ответ должен содержать «Контент-раскладка: вложение», установленный в заголовках, чтобы браузер отображал диалог «открыть/сохранить как». JSON этого не сделает, если вы не выполните пост JSON и не перенаправите URL-адрес – Dimitri
@ Dimitri: да, это уже так.Запрос содержит JSON в теле, ответ содержит CSV с правильными заголовками, включая «Content-Disposition» –