javascript - crear - descargar el archivo csv de la API web en angular js
javascript array to csv (9)
mi controlador API está devolviendo un archivo csv como se ve a continuación:
[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;
}
y mi angularjs que enviará y recibirá el archivo csv se muestra a continuación:
$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, descarga un archivo que se llama document
pero no tiene extensión de tipo de archivo. El contenido del archivo es [Object object]
.
En IE10, no se descarga nada.
¿Qué podría hacer para arreglar esto?
ACTUALIZACIÓN: Esto podría funcionar para ustedes por ahí con el mismo problema: link
Creo que la mejor manera de descargar cualquier archivo generado por la llamada REST es usar el ejemplo window.location:
$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"));
});
En Angular 1.5, use el servicio $window
para descargar un archivo.
angular.module(''app.csv'').factory(''csvService'', csvService);
csvService.$inject = [''$window''];
function csvService($window) {
function downloadCSV(urlToCSV) {
$window.location = urlToCSV;
}
}
En lugar de utilizar Ajax / XMLHttpRequest / $ http para invocar su método WebApi, use un formulario html. De esta forma, el navegador guarda el archivo usando el nombre de archivo y la información del tipo de contenido en los encabezados de respuesta, y no necesita evitar las limitaciones de javascript en el manejo de archivos. También puede usar un método GET en lugar de un POST ya que el método devuelve datos. Aquí hay una forma de ejemplo:
<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>
La última respuesta funcionó para mí durante unos meses, luego dejó de reconocer el nombre del archivo, como adeneo comentó ...
La respuesta de @ Scott aquí está funcionando para mí:
Descargar archivo de un método API Web ASP.NET utilizando AngularJS
La a.download no es compatible con IE. Al menos en las páginas HTML5 "compatibles". :(
Ninguno de esos funcionó para mí en Chrome 42 ...
En cambio, mi directiva ahora usa esta función de link
( base64
hizo funcionar):
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();
});
}
Pruébalo así:
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();
});
basado en la respuesta más excelente en esta pregunta
Tuve que implementar esto recientemente. Pensé en compartir lo que había descubierto;
Para que funcione en Safari, tuve que establecer el objetivo: ''_self'' ,. No te preocupes por el nombre del archivo en Safari. Parece que no es compatible como se menciona aquí; https://github.com/konklone/json/issues/56 ( http://caniuse.com/#search=download )
El siguiente código funciona bien para mí en 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();
Usé la siguiente solución y funcionó para mí.
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();
}