Поддержка загрузки двоичных файлов при использовании ajax невелика, она все еще находится в стадии разработки в виде рабочих проектов .
Простой способ загрузки:
Вы можете заставить браузер загрузить запрошенный файл, просто используя приведенный ниже код, и он поддерживается во всех браузерах и, очевидно, вызовет запрос WebApi точно так же.
$scope.downloadFile = function(downloadPath) {
window.open(downloadPath, '_blank', '');
}
Метод загрузки двоичного файла Ajax:
Использование ajax для загрузки двоичного файла может быть выполнено в некоторых браузерах, и ниже представлена реализация, которая будет работать в последних версиях Chrome, Internet Explorer, FireFox и Safari.
Он использует arraybuffer
тип ответа, который затем преобразуется в JavaScript blob
, который затем либо представляется для сохранения с использованием saveBlob
метода - хотя в настоящее время он присутствует только в Internet Explorer - либо превращается в URL-адрес данных большого двоичного объекта, который открывается браузером, вызывая диалоговое окно загрузки, если MIME-тип поддерживается для просмотра в браузере.
Поддержка Internet Explorer 11 (исправлено)
Примечание. Internet Explorer 11 не любил использовать эту msSaveBlob
функцию, если она была псевдонимом - возможно, это функция безопасности, но, скорее, недостаток. Таким образом, использование var saveBlob = navigator.msSaveBlob || navigator.webkitSaveBlob ... etc.
для определения доступной saveBlob
поддержки вызвало исключение; поэтому код ниже теперь проверяется navigator.msSaveBlob
отдельно. Спасибо? Microsoft
// Based on an implementation here: web.student.tuwien.ac.at/~e0427417/jsdownload.html
$scope.downloadFile = function(httpPath) {
// Use an arraybuffer
$http.get(httpPath, { responseType: 'arraybuffer' })
.success( function(data, status, headers) {
var octetStreamMime = 'application/octet-stream';
var success = false;
// Get the headers
headers = headers();
// Get the filename from the x-filename header or default to "download.bin"
var filename = headers['x-filename'] || 'download.bin';
// Determine the content type from the header or default to "application/octet-stream"
var contentType = headers['content-type'] || octetStreamMime;
try
{
// Try using msSaveBlob if supported
console.log("Trying saveBlob method ...");
var blob = new Blob([data], { type: contentType });
if(navigator.msSaveBlob)
navigator.msSaveBlob(blob, filename);
else {
// Try using other saveBlob implementations, if available
var saveBlob = navigator.webkitSaveBlob || navigator.mozSaveBlob || navigator.saveBlob;
if(saveBlob === undefined) throw "Not supported";
saveBlob(blob, filename);
}
console.log("saveBlob succeeded");
success = true;
} catch(ex)
{
console.log("saveBlob method failed with the following exception:");
console.log(ex);
}
if(!success)
{
// Get the blob url creator
var urlCreator = window.URL || window.webkitURL || window.mozURL || window.msURL;
if(urlCreator)
{
// Try to use a download link
var link = document.createElement('a');
if('download' in link)
{
// Try to simulate a click
try
{
// Prepare a blob URL
console.log("Trying download link method with simulated click ...");
var blob = new Blob([data], { type: contentType });
var url = urlCreator.createObjectURL(blob);
link.setAttribute('href', url);
// Set the download attribute (Supported in Chrome 14+ / Firefox 20+)
link.setAttribute("download", filename);
// Simulate clicking the download link
var event = document.createEvent('MouseEvents');
event.initMouseEvent('click', true, true, window, 1, 0, 0, 0, 0, false, false, false, false, 0, null);
link.dispatchEvent(event);
console.log("Download link method with simulated click succeeded");
success = true;
} catch(ex) {
console.log("Download link method with simulated click failed with the following exception:");
console.log(ex);
}
}
if(!success)
{
// Fallback to window.location method
try
{
// Prepare a blob URL
// Use application/octet-stream when using window.location to force download
console.log("Trying download link method with window.location ...");
var blob = new Blob([data], { type: octetStreamMime });
var url = urlCreator.createObjectURL(blob);
window.location = url;
console.log("Download link method with window.location succeeded");
success = true;
} catch(ex) {
console.log("Download link method with window.location failed with the following exception:");
console.log(ex);
}
}
}
}
if(!success)
{
// Fallback to window.open method
console.log("No methods worked for saving the arraybuffer, using last resort window.open");
window.open(httpPath, '_blank', '');
}
})
.error(function(data, status) {
console.log("Request failed with status: " + status);
// Optionally write the error out to scope
$scope.errorDetails = "Request failed with status: " + status;
});
};
Использование:
var downloadPath = "/files/instructions.pdf";
$scope.downloadFile(downloadPath);
Ноты:
Вам следует изменить свой метод WebApi, чтобы он возвращал следующие заголовки:
Я использовал x-filename
заголовок для отправки имени файла. Это настраиваемый заголовок для удобства, однако вы можете извлечь имя файла из content-disposition
заголовка, используя регулярные выражения.
Вы также должны установить content-type
заголовок mime для своего ответа, чтобы браузер знал формат данных.
Надеюсь, это поможет.