Tengo una aplicación WebApi / MVC para la que estoy desarrollando un cliente angular2 (para reemplazar MVC). Tengo problemas para entender cómo Angular guarda un archivo.
La solicitud está bien (funciona bien con MVC, y podemos registrar los datos recibidos) pero no puedo encontrar la manera de guardar los datos descargados (principalmente sigo la misma lógica que en esta publicación ). Estoy seguro de que es estúpidamente simple, pero hasta ahora simplemente no lo entiendo.
El código de la función componente está debajo. He probado diferentes alternativas, la forma de blob debe ser el camino a seguir por lo que he entendido, pero no hay ninguna función createObjectURL
en URL
. Ni siquiera puedo encontrar la definición de URL
en la ventana, pero aparentemente existe. Si uso el FileSaver.js
módulo me sale el mismo error. Así que supongo que esto es algo que cambió recientemente o aún no se ha implementado. ¿Cómo puedo activar el archivo guardado en A2?
downloadfile(type: string){
let thefile = {};
this.pservice.downloadfile(this.rundata.name, type)
.subscribe(data => thefile = new Blob([data], { type: "application/octet-stream" }), //console.log(data),
error => console.log("Error downloading the file."),
() => console.log('Completed file download.'));
let url = window.URL.createObjectURL(thefile);
window.open(url);
}
En aras de la exhaustividad, el servicio que recupera los datos está debajo, pero lo único que hace es emitir la solicitud y pasar los datos sin mapear si tiene éxito:
downloadfile(runname: string, type: string){
return this.authHttp.get( this.files_api + this.title +"/"+ runname + "/?file="+ type)
.catch(this.logAndPassOn);
}
Respuestas:
El problema es que el observable se ejecuta en otro contexto, por lo que cuando intentas crear la URL var, tienes un objeto vacío y no el blob que deseas.
Una de las muchas formas que existen para resolver esto es la siguiente:
Cuando la solicitud esté lista, llamará a la función "downloadFile" que se define de la siguiente manera:
el blob se ha creado perfectamente y, por lo tanto, la URL var, si no abre la nueva ventana, compruebe que ya ha importado 'rxjs / Rx';
Espero que esto pueda ayudarte.
fuente
this._reportService.getReport()
y qué devuelve?getReport()
regresa athis.http.get(PriceConf.download.url)
Prueba esto !
1 - Instalar dependencias para mostrar guardar / abrir archivo emergente
2- Crea un servicio con esta función para recibir los datos
3- En el componente, analiza el blob con 'file-saver'
Esto funciona para mi!
fuente
Si no es necesario agregar encabezados en la solicitud, para descargar un archivo en Angular2 se puede hacer una sencilla :
en su componente
fuente
authHttp
!Esto es para personas que buscan cómo hacerlo usando HttpClient y File-Saver:
Clase de servicio API:
Componente:
fuente
¿Qué tal esto?
Yo podría hacer con eso.
No necesita paquete adicional.
fuente
Como mencionó Alejandro Corredor , es un simple error de alcance. Se
subscribe
ejecuta de forma asincrónica yopen
debe colocarse en ese contexto, de modo que los datos terminen de cargarse cuando activemos la descarga.Dicho esto, hay dos formas de hacerlo. Como los documentos recomiendan, el servicio se encarga de obtener y asignar los datos:
Luego, en el componente solo nos suscribimos y tratamos con los datos mapeados. Hay dos posibilidades El primero , como se sugiere en la publicación original, pero necesita una pequeña corrección como señaló Alejandro:
La segunda forma sería usar FileReader. La lógica es la misma, pero podemos esperar explícitamente a que FileReader cargue los datos, evitando el anidamiento y resolviendo el problema asíncrono.
Nota: Estoy tratando de descargar un archivo de Excel, y aunque la descarga se activa (por lo que esto responde a la pregunta), el archivo está dañado. Vea la respuesta a esta publicación para evitar el archivo corrupto.
fuente
res
en el blob y realmente lo deseares._body
. Sin embargo,_body
es una variable privada y no accesible. A partir de hoy.blob()
y.arrayBuffer()
en un objeto de respuesta http no se han implementado en Angular 2.text()
yjson()
son las únicas dos opciones, pero ambas van a confundir su cuerpo. ¿Has encontrado una solución?<a href=""></a>
para descargar un archivo.Descargue la solución * .zip para angular 2.4.x: debe importar ResponseContentType de '@ angular / http' y cambiar responseType a ResponseContentType.ArrayBuffer (de forma predeterminada, ResponseContentType.Json)
fuente
Para versiones angulares más nuevas:
fuente
La descarga de archivos a través de ajax siempre es un proceso doloroso y, en mi opinión, es mejor dejar que el servidor y el navegador hagan este trabajo de negociación de tipo de contenido.
Creo que es mejor tener
para hacerlo. Esto ni siquiera requiere que se abran ventanas nuevas y cosas así.
El controlador MVC como en su muestra puede ser como el siguiente:
fuente
Estoy usando Angular 4 con el objeto 4.3 httpClient. Modifiqué una respuesta que encontré en el Blog técnico de Js que crea un objeto de enlace, lo usa para realizar la descarga y luego lo destruye.
Cliente:
El valor de this.downloadUrl se ha configurado previamente para que apunte a la API. Estoy usando esto para descargar archivos adjuntos, así que sé la identificación, el tipo de contenido y el nombre de archivo: estoy usando una API MVC para devolver el archivo:
La clase de archivo adjunto se ve así:
El repositorio de filerep devuelve el archivo de la base de datos.
Espero que esto ayude a alguien :)
fuente
Para aquellos que usan Redux Pattern
Agregué en el protector de archivos como @Hector Cuevas nombrado en su respuesta. Usando Angular2 v. 2.3.1, no necesitaba agregar el @ types / file-saver.
El siguiente ejemplo es descargar una revista como PDF.
Las acciones del diario
Los efectos del diario
El servicio de revista
El servicio HTTP
El reductor de diario Aunque esto solo establece los estados correctos utilizados en nuestra aplicación, todavía quería agregarlo para mostrar el patrón completo.
Espero que esto sea útil.
fuente
Comparto la solución que me ayudó (cualquier mejora es muy apreciada)
En su servicio 'pservice':
Parte componente :
En la parte componente, llama al servicio sin suscribirse a una respuesta. La suscripción para obtener una lista completa de los tipos de mimo de openOffice, consulte: http://www.openoffice.org/framework/documentation/mimetypes/mimetypes.html
fuente
Será mejor si intentas llamar al nuevo método dentro de ti
subscribe
downloadFile(data)
Función interior que necesitamos hacerblock, link, href and file name
fuente
Para descargar y mostrar archivos PDF , un código recortado muy similar es el siguiente:
fuente
Aquí hay algo que hice en mi caso:
Se hace referencia a la solución desde aquí.
fuente
Actualice la respuesta de Héctor utilizando el protector de archivos y HttpClient para el paso 2:
fuente
Obtuve una solución para descargar desde angular 2 sin corromper, usando spring mvc y angular 2
Primero, mi tipo de devolución es: - ResponseEntity from java end. Aquí estoy enviando byte [] array tiene tipo de retorno desde el controlador.
2º- para incluir el protector de archivos en su espacio de trabajo, en la página de índice como:
3º- en el componente ts escriba este código:
Esto le dará el formato de archivo xls. Si desea otros formatos, cambie el tipo de medio y el nombre del archivo con la extensión correcta.
fuente
Enfrenté este mismo caso hoy, tuve que descargar un archivo pdf como archivo adjunto (el archivo no debería mostrarse en el navegador, sino descargarse). Para lograr eso descubrí que tenía que obtener el archivo en un Angular
Blob
y, al mismo tiempo, agregar unContent-Disposition
encabezado en la respuesta.Esto fue lo más simple que pude obtener (Angular 7):
Dentro del servicio:
Luego, cuando necesito descargar el archivo en un componente, simplemente puedo:
ACTUALIZAR:
Se eliminó la configuración innecesaria del encabezado del servicio
fuente
El siguiente código me funcionó
fuente
Las respuestas que encontré hasta ahora carecían de perspicacia y advertencias. Podrías y deberías estar atento a incompatibilidades con IE10 + (si te importa).
Este es el ejemplo completo con la parte de aplicación y la parte de servicio posterior. Tenga en cuenta que configuramos la observación: "respuesta" para capturar el encabezado del nombre de archivo. Tenga en cuenta también que el encabezado Content-Disposition debe ser configurado y expuesto por el servidor, de lo contrario, el Angular HttpClient actual no lo transmitirá. Agregué un código de dotnet core para eso a continuación.
Dotnet core, con Content-Disposition y MediaType
fuente
fuente
En pocas palabras el
url
comohref
de la siguiente manera.fuente
<a href="my_url" download="myfilename">Download file</a>
my_url debe tener el mismo origen, de lo contrario, se redirigirá a esa ubicación
fuente
También puede descargar un archivo directamente desde su plantilla donde utiliza el atributo de descarga y
[attr.href]
puede proporcionar un valor de propiedad del componente. Esta solución simple debería funcionar en la mayoría de los navegadores.Referencia: https://www.w3schools.com/tags/att_a_download.asp
fuente
Si solo envía los parámetros a una URL, puede hacerlo de esta manera:
en el servicio que recibe los parámetros
fuente
Esta respuesta sugiere que no puede descargar archivos directamente con AJAX, principalmente por razones de seguridad. Así que describiré lo que hago en esta situación,
01. Agregue
href
atributo en su etiqueta de anclaje dentro delcomponent.html
archivo,por ejemplo: -
02. Realice todos los pasos siguientes
component.ts
para evitar el nivel de seguridad y abrir el cuadro de diálogo emergente Guardar como,por ejemplo: -
fuente
Bueno, escribí un código inspirado en muchas de las respuestas anteriores que deberían funcionar fácilmente en la mayoría de los escenarios en los que el servidor envía un archivo con un encabezado de disposición de contenido, sin ninguna instalación de terceros, excepto rxjs y angular.
Primero, cómo llamar al código desde su archivo componente
Como puede ver, es básicamente la llamada de backend promedio de angular, con dos cambios
Una vez que el archivo se obtiene del servidor, en principio, delego toda la tarea de guardar el archivo en la función auxiliar, que guardo en un archivo separado, e importarlo a cualquier componente que necesite
¡Ya no hay nombres de archivos GUID crípticos! Podemos usar cualquier nombre que proporcione el servidor, sin tener que especificarlo explícitamente en el cliente, o sobrescribir el nombre de archivo proporcionado por el servidor (como en este ejemplo). Además, uno puede fácilmente, si es necesario, cambiar el algoritmo de extracción del nombre de archivo de la disposición de contenido para satisfacer sus necesidades, y todo lo demás no se verá afectado; en caso de error durante dicha extracción, simplemente pasará 'nulo' como el nombre del archivo.
Como otra respuesta ya señaló, IE necesita un tratamiento especial, como siempre. Pero con el borde de cromo en unos meses, no me preocuparía por eso mientras construyo nuevas aplicaciones (con suerte). También está la cuestión de revocar la URL, pero no estoy tan seguro de eso, así que si alguien pudiera ayudar con eso en los comentarios, sería increíble.
fuente
Si una pestaña se abre y se cierra sin descargar nada, intenté seguir con el enlace de anclaje falso y funcionó.
fuente