mon contrôleur API renvoie un fichier csv comme indiqué 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 mes angularjs qui vont envoyer et recevoir le fichier csv sont affichés 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();
});
};
En chrome, il télécharge un fichier appelé document
mais n’ayant aucune extension de type de fichier . Le contenu du fichier est [Object object]
.
Dans IE10, rien n'est téléchargé.
Que pourrais-je faire pour résoudre ce problème?
UPDATE: Cela pourrait fonctionner pour vous autres avec le même problème: link
Essayez comme ça:
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 plus excellente réponse 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 fonctionné pour moi dans Chrome 42 ...
Au lieu de cela ma directive utilise maintenant cette fonction link
(base64
l'a fait fonctionner):
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 le commentait adeneo ...
La réponse de @ Scott ici fonctionne pour moi:
Téléchargez le fichier à partir d’une méthode d’API Web ASP.NET avec AngularJS
J'ai dû implémenter ceci récemment. Pensée de partager ce que j'avais trouvé;
Pour que cela fonctionne dans Safari, je devais définir la cible: '_self' ,. Ne vous inquiétez pas du nom de fichier dans Safari. On dirait que ce 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();
Dans Angular 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;
}
}
Plutôt que d'utiliser Ajax/XMLHttpRequest/$ http pour appeler votre méthode WebApi, utilisez un formulaire HTML. Ainsi, le navigateur enregistre le fichier à l'aide des informations de nom de fichier et de type de contenu figurant dans les en-têtes de réponse. Il n'est pas nécessaire de contourner les limitations de JavaScript pour la gestion des fichiers. Vous pouvez également utiliser une méthode GET plutôt qu'un POST lorsque la méthode renvoie 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>
Je pense que la meilleure façon de télécharger un fichier généré par l'appel de REST est d'utiliser window.location 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"));
});
Le fichier a.download n'est pas pris en charge par IE. Au moins sur les pages HTML5 "prises en charge". :(