La compatibilidad para descargar archivos binarios al usar ajax no es excelente, todavía está en desarrollo como borradores de trabajo .
Método de descarga simple:
Puede hacer que el navegador descargue el archivo solicitado simplemente usando el código a continuación, y esto es compatible con todos los navegadores, y obviamente activará la solicitud de WebApi de la misma manera.
$scope.downloadFile = function(downloadPath) {
window.open(downloadPath, '_blank', '');
}
Método de descarga binaria Ajax:
El uso de ajax para descargar el archivo binario se puede hacer en algunos navegadores y a continuación se muestra una implementación que funcionará en las últimas versiones de Chrome, Internet Explorer, Firefox y Safari.
Utiliza un arraybuffer
tipo de respuesta, que luego se convierte en JavaScript blob
, que luego se presenta para guardar usando el saveBlob
método, aunque actualmente solo está presente en Internet Explorer, o se convierte en una URL de datos de blob que abre el navegador, activando el diálogo de descarga si el tipo mime es compatible para ver en el navegador.
Soporte de Internet Explorer 11 (fijo)
Nota: a Internet Explorer 11 no le gustaba usar la msSaveBlob
función si tenía un alias, quizás una característica de seguridad, pero más probablemente un defecto, por lo que usar var saveBlob = navigator.msSaveBlob || navigator.webkitSaveBlob ... etc.
para determinar el saveBlob
soporte disponible causó una excepción; por lo tanto, el siguiente código ahora prueba por navigator.msSaveBlob
separado. ¿Gracias? 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;
});
};
Uso:
var downloadPath = "/files/instructions.pdf";
$scope.downloadFile(downloadPath);
Notas:
Debe modificar su método WebApi para devolver los siguientes encabezados:
He usado el x-filename
encabezado para enviar el nombre del archivo. Este es un encabezado personalizado para su comodidad, sin embargo, puede extraer el nombre de archivo del content-disposition
encabezado utilizando expresiones regulares.
También debe configurar el content-type
encabezado mime para su respuesta, de modo que el navegador conozca el formato de datos.
Espero que esto ayude.