Saltar al contenido

Categoría: Angular

Descargar Archivo en Angular

Bueno, con este post espero complementar el post anterior:

Lo hago con angular, por que cuando me toco revisarlo en el trabajo use angular para hacerlo. Pero, me parece que encontrarán algunas funciones que les pueden servir, dado que son javascript puro.

Basicamente, tenemos una aplicación creada usando el tipico:

ng new app-name

Le he instalado algunas librerias para poder tener algo más decente que un alert, otras que las podrán revisar en el código fuente que como siempre dejo disponible. La demás lógica la he realizado en el «app.component» que se crea por defecto. Revisemos que hemos creado en nuestro «app.component.html».

Adicion de botón de descarga

Al html inicial que se genera con nuestro nuevo proyecto ded angular, estoy adicionandole un botón de carga.

app.component.ts

Primer metodo, descarga el excel
Segundo método, le da formato como archivo y lo guarda en la pc

Acá, tenemos dos métodos, uno que nos permitirá descargar el array de bytes consumiendo el servicio, y el otro que obtendrá esta información, y lo descargará a nuestra máquina. Recordemos que si queremos que nuestro navegador abra una ventana para elegir donde guardar el archivo, se debe configurar en el mismo browser, de no ser así, el navegador lo descargará automáticamente en una carpeta (de descargas probablemente).

Finalmente, veamos que tenemos en nuestro servicio.

Consumo del servicio

Como se puede ver, es necesario en el header, indicar que esperamos un tipo «blob». Hagamos ahora una prueba.

Abrimos nuestra aplicación, podemos ver nuestro botón, lo presionamos

Recordemos que tenemos que tener el servicio corriendo en el mismo puerto en el que se está poniendo en el servicio.

Petición al servicio.

Sale la petición a nuestro servicio

La petición, llega al endpoint.

Llega nuestra petición al servicio

Podemos ver acá la respuesta que estamos recibiendo de nuestro servicio.

Se descarga el archivo.

Descarga final del archivo

Bueno, así finalizamos esta serie de post de generar un archivo excel y descargarlo desde una web en angular. Espero que les sirva, dejo el video con la explicación y el codigo fuente en github por si les interesa.

REPO: GITHUB

Saludos.

11 comentarios

Autenticación en Angular con JWT

Hola, aprovechando un poco el paro que estamos teniendo en Perú por un aislamiento que a decretado el estado me di un tiempo entre el trabajo remoto y otras responsabilidades para hacer una pequeña demo sobre el uso de autenticación en Angular, específicamente como podemos valernos de interceptores y guards para poder trabajar con json web tokens (JWT).

Hago la demo de este punto en especifico por que recibi un par de preguntas la semana pasada sobre este tema y me di cuenta que en su momento para mi también entender ciertos conceptos y como se usaban me costo un poco y decidí hacer una demo y un post sobre esto.

Para explicar un poco como he decidido dividir la demo, el proyecto en angular se ha desarrollado desde 0, valiéndome de angular cli para generar la estructura básica de angular y sobre esta cree dos componentes una publico y otro protegido además de otras carpetas para los intercetores, guard y servicios. Del lado del backend, para generar nuestros JWT me estoy valiendo de una aplicación que ya tengo realizada y sólo he modificado el endpoint para generar el token y retornarlo. Veamos con más detalle nuestra aplicación en angular.

Estructura del proyecto en angular

Veamos que tenemos en nuestro «app.module»:

Configuración en AppModule
  • declarations: Se declaran los dos componentes que vamos a usar en nuestra demo el público y el privado.
  • imports: Importamos «HttpClientModule» para poder realizar conexiones http, «FormsModule» y «ReactiveFormsModule» para poder crear nuestro formulario de login. Los otros dos imports se añaden automaticamente al generar el proyecto.
  • providers: Acá estamos registrando nuestro servicio de autenticación y además registramos nuestros interceptor.

Ahora revisemos el «app-routing.module.ts»:

Configuración del AppRoutingModule

Lo único que debe importarnos acá es el registro de los routes, como podemos ver tenemos un array con dos objetos uno de ellos es nuestro componente público al cual estamos direccionando la ruta por defecto y el otro objeto es para nuestra componente protegido, en el cual es necesario indicar que para activarse (canActivate) se usará nuestro guard que se detallará más adelante.

Rapidamente, revisemos los componentes que se han creado:

Public

Configuración en el componente public
Configuración de la vista del componente public

Veamos un que tenemos en este componente. Declaramos un formulario de login típico que al realizar el submit llama al método «onSubmit()», tenemos la inidicalización de nuestro formulario y en el submit se valida si se ingresaron valores de usuario y contraseña y de ser esto así llama al servicio de login. Si este último llamado es correcto nos subscribimos a la respuesta para poder guardar el token en el localstorage y hacemos un navigate con el route a nuestro componente protegido «protected».

Protected

Configuración del componente protected

Este componente es literalmente un «ng g c protected». Dado que la demo se centra en llegar a el, no en lo que este nos va a mostrar. Veamos que sucede cuando en nuestro componente public se ejecuta la linea:

this.router$.navigate(['/protected']);

Se vemos el código, esta linea se ejecuta si y sólo si la petición que se realizo al backend por el token fue correcta y antes de realizarse se graba este token en el localstorage del browser. Cuando se ejecute, es donde entra a tallar nuestro guard. Veamos que lógica se tiene ahí.

Configuración del guard

Lo que tenemos acá es una clase creada por notros que implemente «CanActivate» y en esta implementación lo que yo estoy haciendo es intentando obtener el token que se debío grabar si la autenticación es correcta, si se obtuviera entonces retorno true y esto hace que angular nos redirija a nuestra url solicitada. De no ser asi, le estoy indicando que envíe al usuario a la ruta básica (public para nuestro caso) y que retorne false.

Revisemos para finalizar el consumo del servicio de autenticación y el interceptor.

Servicio de autenticación

Lo interesante acá es el interceptor ya se explico donde debemos registrarlo, ahora veamos como se ha implementado y que nos permite realizar.

Implementación interceptor parte I
Implementación interceptor parte II

Veamos como en el constructor de nuestro interceptor nos subscribimos a los cambios en el route, se valida el tipo de evento y luego se le indica que siga avanzando y termina entrando en nuestro método implementado «intercept» en este método validamos la url que se intenta consumir con una expresión regular, luego de verifica si existiera un token en nuestro localstorage, de ser este es el caso se clona el request inicial y se le añade el header de «Authorization» con el bearer que corresponde. Del mismo modo, se añade el header del «Content-Type» y por úlitmo siempre se añade el header del formato de la data esperada con el «Accept». Además, incrementamos los request pendiente de realizar con el «pendingRequests» y finalmente en el return le hacemos un pipe al observable que va a retornar de la solicitud. Cuando esta solicitud sea exitosa entrará a nuestra subscripción en nuestro componente que ya revisamos previamente, en el caso contrario entrará al «catcherror» y acá simplemente haremos un throwerror. Consideremos que siempre entrará al método «finalize» y es acá donde reducimos nuestras request pendientes por que ya se realizo.

Ya para terminar con este post – ahora si de verdad – veamos que hace nuestro backend.

Backend para generar el JWT

Como se puede observar, se a modificado un poco el funcionamiento del método para que basicamente reciba un usuario y contraseña, genere un token y lo retorne.

Con esto terminamos la demo y aunque el post salio un poco más extenso de lo que hubiera querido, me parece que se cubre todo a detalle. El funcionamiento de la demo pueden revisarla el video que adjunto y como siempre dejo también acceso al repositorio donde pueden encontrar el código fuente del frontend.

REPO: GITHUB

Saludos.

2 comentarios

Upload File Input Component con Angular Material

Desde hace algún tiempo que vengo trabajando con Angular, recientemente en un freelo me vi en la necesidad de hacer la carga de un archivo a un controllador en net core. Actualmente en este proyecto se esta usando Angular Material y me di con la sorpresa que en esta librería no se tienen ninguna alternativa a un input type file.

Luego de buscar un poco y no encontrar una alternativa que me llamara la atención, decidí ver la forma de crear una. Les comparto esta demo por si a alguien le puede resultar útil.

Primero, necesitamos crear nuestro nuevo proyecto en angular, instalar la librería de angular material, crear el componente para cargar el archivo y finalmente, crear un modulo adicional para que concentre todos los módulos correspondientes de angular material, para esto ejecutamos en la consola del vscode los típicos comandos:

ng new UploadFileAngularMaterial
cd UploadFileAngularMaterial
npm install --save @angular/material @angular/cdk @angular/animations
ng g m /modules/material
ng g c file-upload

Del lado de la configuración del angular material, no me explayaré mucho dado que hay muchos tutoriales en la red que pueden dar más ejemplo y también puede verlo en el repositorio al final del post.

Para usar los material icons, estoy en el index de la aplicación poniendo el link a la url:

<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">

Veamos ahora si lo importante de esta demo:

File-Upload

El html del componente tendrá la siguiente estructura:

HTML del componente File-Upload

Como se puede observar, tenemos un botón para hacerla carga (una imagen), y debajo de este una lista de los archivos que queramos cargar, en la cual se muestra el nombre del archivo, una barra de progreso, y dos iconos que actúan a modo de botones para reintentar en caso la carga no se haya podido efectuar y para cancelar la carga. Finalmente, nuestro input type file.

Sólo explicaré los métodos más importantes del componente dado que se tienen creado varios:

Variables del Componente

Para nuestro componente, tenemos algunas variables que pueden ser input del componente, y un output del tipo string. Además, la información que se selecciones los ‘files’ so del tipo ‘FileUploadModel’, paso a detallar lo que contiene este model.

Model FileUploadModel

Este modelo posee cierta información que usaremos para manejar la carga del archivo, los estamos que tiene, si se puede re-intentar o cancelar así como las subscripciones que se realizan cuando se hacen las peticiones http.

onClick al botón

Cada ves que se realice un click al botón, se está obteniendo el input type file y se busca el evento ‘onchange’, mediante el cual se obtiene los items seleccionados (archivos de texto para el demo). Dado que el evento ‘onchange’, se va activar cuando este cambie, se llama al evento ‘click’ para que abra el buscar de archivos desde el navegador, de manera que cuando estos sean seleccionados se carguen los archivos, y recién se llama al método ‘uploadFiles’.

uploadFiles

Se empieza a iterar sobre los archivos seleccionados que se llenaron en el evento ‘onchange’ y cada uno de estos estos serán enviados al método ‘uploadFile’.

uploadFile

Este es el método que se encarga de hacer la carga del archivo, para la demo estoy usando un api pública «http://file.io» que te permite realizar la carga de archivos. También se podría llamar a algún service de ser necesario o el modo en le cual deseen consumir servicios desde su aplicativo. Acá, estamos inicializando un HttpRequest del tipo post, y asignado el request a nuestro ‘sub’ que es parte de nuestra entidad. Adicionalmente, vamos a mapear un evento para poder determinar el avance del progress conforme se va cargando el archivo, tenemos una suscripción para manejar lo que nos retorne la suscripción en caso de que la respuesta HTPP sea del tipo 200, si fuera alguna respuesta HTTP de error, entrará a nuestro ‘catchError’. De ser correcto, limpiamos el archivo y le enviamos la respuesta al output del tipo eventEmitter, al componente que este llamandonos. Veamos una demo de como se está dando todo este proceso:

Presionamos el botón
Luego de seleccionarlo, se carga al array de archivos y se envia al uploadfiles
Esta por llevarse a cabo la solicitud al endpoint
Mientras el archivo carga, se ve la barra de carga, nombre del archivo y un botón de cancelar
Cuando cargo correctamente, se elimina el archivo del listado y se envía el output
Se envia a un console.log el resultado del envio del archivo

Si quisieramos revisar si la carga fue correcta, podemos abrir el link que se adjunta en el response, teniendo el siguiente resultado.

Respuesta del endpoint

Aún cuando el dedsarrollo del componente me tomo mas tiempo del que hubiera deseado, es una buena idea tenerlo como una herramienta más en el repertorio. Dejo un video de la creación del proyecto y las pruebas que se han realizado, además del link al repositorio.

REPO: GITHUB

13 comentarios