télécharger le fichier csv de l'api web en angle js
mon contrôleur API retourne un fichier csv comme vu ci-dessous:
[HttpPost]
public HttpResponseMessage GenerateCSV(FieldParameters fieldParams)
{
var output = new byte[] { };
if (fieldParams!= null)
{
using (var stream = new MemoryStream())
{
this.SerializeSetting(fieldParams, stream);
stream.Flush();
output = stream.ToArray();
}
}
var result = new HttpResponseMessage(HttpStatusCode.OK) { Content = new ByteArrayContent(output) };
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
FileName = "File.csv"
};
return result;
}
et mon angularjs qui enverra et recevra le fichier csv est montré ci-dessous:
$scope.save = function () {
var csvInput= extractDetails();
// File is an angular resource. We call its save method here which
// accesses the api above which should return the content of csv
File.save(csvInput, function (content) {
var dataUrl = 'data:text/csv;utf-8,' + encodeURI(content);
var hiddenElement = document.createElement('a');
hiddenElement.setAttribute('href', dataUrl);
hiddenElement.click();
});
};
dans chrome, il télécharge un fichier qui s'appelle document
mais n'a pas d'extension de type de fichier.
Le contenu du fichier est [Object object]
.
Dans IE10, rien n'est téléchargé.
que pouvais-je faire pour arranger ça?
mise à jour: Cela pourrait fonctionner pour vous les gars là-bas avec le même problème: lien
9 réponses
Essayer comme :
File.save(csvInput, function (content) {
var hiddenElement = document.createElement('a');
hiddenElement.href = 'data:attachment/csv,' + encodeURI(content);
hiddenElement.target = '_blank';
hiddenElement.download = 'myFile.csv';
hiddenElement.click();
});
basé sur la réponse la plus excellente dans cette question
j'ai utilisé la solution ci-dessous et cela a fonctionné pour moi.
if (window.navigator.msSaveOrOpenBlob) {
var blob = new Blob([decodeURIComponent(encodeURI(result.data))], {
type: "text/csv;charset=utf-8;"
});
navigator.msSaveBlob(blob, 'filename.csv');
} else {
var a = document.createElement('a');
a.href = 'data:attachment/csv;charset=utf-8,' + encodeURI(result.data);
a.target = '_blank';
a.download = 'filename.csv';
document.body.appendChild(a);
a.click();
}
aucun de ceux qui ont travaillé pour moi dans Chrome 42...
à la place, ma directive utilise maintenant cette fonction link
( base64
made it work):
link: function(scope, element, attrs) {
var downloadFile = function downloadFile() {
var filename = scope.getFilename();
var link = angular.element('<a/>');
link.attr({
href: 'data:attachment/csv;base64,' + encodeURI($window.btoa(scope.csv)),
target: '_blank',
download: filename
})[0].click();
$timeout(function(){
link.remove();
}, 50);
};
element.bind('click', function(e) {
scope.buildCSV().then(function(csv) {
downloadFile();
});
scope.$apply();
});
}
la dernière réponse a fonctionné pour moi pendant quelques mois, puis a cessé de reconnaître le nom de fichier, comme adeneo a commenté ...
la réponse de @Scott fonctionne pour moi:
télécharger le fichier d'un ASP.NET méthode de L'API Web utilisant AngularJS
j'ai dû mettre en oeuvre ceci récemment.
pour le faire fonctionner en Safari, j'ai dû fixer l'objectif: '_self',. Ne vous inquiétez pas pour le nom de fichier dans Safari. On dirait qu'il n'est pas supporté comme mentionné ici; https://github.com/konklone/json/issues/56 ( http://caniuse.com/#search=download )
le code ci-dessous fonctionne très bien pour moi dans Mozilla, Chrome & Safari;
var anchor = angular.element('<a/>');
anchor.css({display: 'none'});
angular.element(document.body).append(anchor);
anchor.attr({
href: 'data:attachment/csv;charset=utf-8,' + encodeURIComponent(data),
target: '_self',
download: 'data.csv'
})[0].click();
anchor.remove();
The A. le téléchargement n'est pas supporté par IE. Au moins sur les pages "supportées" par HTML5. : (
plutôt que D'utiliser Ajax / XMLHttpRequest / $http pour invoquer votre méthode WebApi, utilisez un formulaire html. De cette façon, le navigateur enregistre le fichier en utilisant le nom du fichier et les informations de type de contenu dans les en-têtes de réponse, et vous n'avez pas besoin de travailler autour des limites de javascript sur le traitement de fichier. Vous pouvez également utiliser une méthode GET plutôt qu'un POST car la méthode retourne des données. Voici un exemple de formulaire:
<form name="export" action="/MyController/Export" method="get" novalidate>
<input name="id" type="id" ng-model="id" placeholder="ID" />
<input name="fileName" type="text" ng-model="filename" placeholder="file name" required />
<span class="error" ng-show="export.fileName.$error.required">Filename is required!</span>
<button type="submit" ng-disabled="export.$invalid">Export</button>
</form>
dans L'angle 1.5, utilisez le service $window
pour télécharger un fichier.
angular.module('app.csv').factory('csvService', csvService);
csvService.$inject = ['$window'];
function csvService($window) {
function downloadCSV(urlToCSV) {
$window.location = urlToCSV;
}
}
je pense que la meilleure façon de télécharger un fichier généré par REST call est d'utiliser window.emplacement exemple:
$http({
url: url,
method: 'GET'
})
.then(function scb(response) {
var dataResponse = response.data;
//if response.data for example is : localhost/export/data.csv
//the following will download the file without changing the current page location
window.location = 'http://'+ response.data
}, function(response) {
showWarningNotification($filter('translate')("global.errorGetDataServer"));
});