Le support du téléchargement de fichiers binaires en utilisant ajax n'est pas génial, il est encore en cours de développement en tant que brouillons de travail .
Méthode de téléchargement simple:
Vous pouvez demander au navigateur de télécharger le fichier demandé simplement en utilisant le code ci-dessous, ce qui est pris en charge dans tous les navigateurs et déclenchera évidemment la requête WebApi de la même manière.
$scope.downloadFile = function(downloadPath) {
window.open(downloadPath, '_blank', '');
}
Méthode de téléchargement binaire Ajax:
L'utilisation d'ajax pour télécharger le fichier binaire peut être effectuée dans certains navigateurs et ci-dessous se trouve une implémentation qui fonctionnera dans les dernières versions de Chrome, Internet Explorer, FireFox et Safari.
Il utilise un arraybuffer
type de réponse, qui est ensuite converti en JavaScript blob
, qui est ensuite présenté pour être enregistré à l'aide de la saveBlob
méthode - bien que ce ne soit actuellement présent que dans Internet Explorer - ou transformé en une URL de données blob qui est ouverte par le navigateur, déclenchant la boîte de dialogue de téléchargement si le type mime est pris en charge pour l'affichage dans le navigateur.
Prise en charge d'Internet Explorer 11 (fixe)
Remarque: Internet Explorer 11 n'aimait pas utiliser la msSaveBlob
fonction si elle avait été aliasée - peut-être une fonction de sécurité, mais plus probablement une faille, donc l'utilisation var saveBlob = navigator.msSaveBlob || navigator.webkitSaveBlob ... etc.
pour déterminer le saveBlob
support disponible a provoqué une exception; d'où pourquoi le code ci-dessous teste maintenant navigator.msSaveBlob
séparément. Merci? 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;
});
};
Usage:
var downloadPath = "/files/instructions.pdf";
$scope.downloadFile(downloadPath);
Remarques:
Vous devez modifier votre méthode WebApi pour renvoyer les en-têtes suivants:
J'ai utilisé l'en- x-filename
tête pour envoyer le nom de fichier. Il s'agit d'un en-tête personnalisé pour plus de commodité, vous pouvez cependant extraire le nom de fichier de l'en- content-disposition
tête à l'aide d'expressions régulières.
Vous devez également définir l'en- content-type
tête mime pour votre réponse, afin que le navigateur connaisse le format des données.
J'espère que ça aide.