Contenido
- Introducción
- Configurar proyecto de firebase
- Crear proyecto de Angular
- Conectar angular con firebase
Introducción
En este post se muestra como realizar la carga de archivos a cloud storage a través de firebase.
Configurar proyecto de firebase
Para configurar el proyecto de firebase se debe realizar los siguientes pasos:
Acceder a firebase console y crear un nuevo proyecto.
Habilitar storage en firebase.
Para esto en el menú lateral se encuentra la opción de storage, al ingresar a dicha opción se da click en botón de comenzar y se siguen los pasos.
Finalizado el proceso la ventana de storage se mostrara de la siguiente manera:
Si se desea se puede ir a cloud storage y verificar la creación de bucket
Por ultimo se va a la pestaña de Rules y se cambia la regla para que no solicite autenticarse para realizar la carga de los archivos.
La cual queda de la siguiente manera:
Agregar app en firebase
En la ventana principal del proyecto se encuentra la opción de agregar app, donde muestra diferentes plataformas a seleccionar en este caso se selecciona Web y se siguen los pasos.
.
Crear proyecto de Angular
Si desea puede omitir este paso y clonar el repositorio https://github.com/plinio141/test-storage-angular.
Para crear y configurar el proyecto de Angular utilizar los siguientes comandos:
ng new test-storage-angular
cd test-storage-angular
ng add @angular/material
npm i -s @angular/flex-layout
Posteriormente agregar al app.module lo siguiente
import {MatButtonModule} from '@angular/material/button';
import { FlexLayoutModule } from '@angular/flex-layout';
@NgModule({
...
imports: [
...
MatButtonModule,
FlexLayoutModule
],
...
})
Conectar angular con firebase
Para esto seguir los siguientes pasos:
Tomar el Json que genero firebase al registrar la aplicación y agregarlo al archivo de environment en angular de la siguiente manera:
export const environment = {
production: false,
firebaseConfig: {
apiKey: "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
authDomain: "XXXXXXXXXXXXXXXXXXXXXXXXXXXX",
databaseURL: "XXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
projectId: "XXXXXXXXXXXXXXXXXXXXX",
storageBucket: "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
messagingSenderId: "XXXXXXXXXXXXXXXXXXXXXXXXX",
appId: "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
}
};
Instalar librería firebase y @angular/fire
npm i --save firebase
npm i @angular/fire --save
Importar AngularFireModule, AngularFireStorageModule y environment en el app.module
import { AngularFireModule } from '@angular/fire';
import { AngularFireStorageModule } from '@angular/fire/storage';
import { environment } from '../environments/environment';
Agregar a los imports las siguientes lineas:
AngularFireModule.initializeApp(environment.firebaseConfig),
AngularFireStorageModule,
El app.module quedaría de la siguiente manera:
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AngularFireModule } from '@angular/fire';
import { AngularFireStorageModule } from '@angular/fire/storage';
import { MatButtonModule } from '@angular/material/button';
import { FlexLayoutModule } from '@angular/flex-layout';
import { AppComponent } from './app.component';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { environment } from '../environments/environment';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
BrowserAnimationsModule,
MatButtonModule,
FlexLayoutModule,
AngularFireModule.initializeApp(environment.firebaseConfig),
AngularFireStorageModule,
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
Ahora se crea una interfaz gráfica simple que contenga un input tipo file y un botón que tendrá el evento de carga del archivo en este caso se hará en el app.component.html
<section fxLayout="column" fxLayoutAlign="space-around center" fxFlex="100" fxLayoutGap="20px">
<div class="label" fxFlex="30">Archivo</div>
<div fxFlex="30"><input type="file" name="file"/></div>
<div fxFlex="30">
<button mat-flat-button color="primary">Cargar</button>
</div>
</section>
Si desea puede agregar los siguientes estilos:
section {
padding: 10px;
}
.label {
font-size: 30px;
}
Ahora en app.component.ts se agrega una propiedad llamada file de tipo File y se crea una función que va capturar el evento de selección de una imagen.
file: File;
onFileSelect(event) {
if (event.target.files.length > 0) {
this.file = event.target.files[0];
}
}
Se agrega al input file el evento change apuntando a la función anteriormente creada.
<div fxFlex="30"><input type="file" name="file" (change)="onFileSelect($event)"/></div>
En el app.component.ts importar el AngularFireStorage y agregar una nueva función que sera la encargada de cargar los archivos.
import { AngularFireStorage } from '@angular/fire/storage';
...
constructor(
private storage: AngularFireStorage
){}
...
uploadFile() {
const filePath = this.file.name;
// Crea una referencia de acceso
const fileRef = this.storage.ref(filePath);
fileRef.put(this.file);
}
Agregar al botón Cargar el evento click para que cargue el archivo.
<button mat-flat-button color="primary" (click)="uploadFile()">Cargar</button>
Con esto ya se carga un archivo a cloud storage por medio de firebase, pero visualmente no se identifica que ya fue cargado el archivo así que se va crear un mensaje de carga completa. Para esto se añade en el html lo siguiente:
<div class="label" fxFlex="30" *ngIf="completed">Archivo cargado</div>
Además, en el app.component.ts se agrega una propiedad para mostrar y ocultar el mensaje de carga completa, de igual manera se debe modificar la función de uploadFile para actualizar la propiedad completed cuando se termine de cargar el archivo.
uploadFile() {
this.completed = false;
const filePath = this.file.name;
// Crea una referencia de acceso
const fileRef = this.storage.ref(filePath);
fileRef.put(this.file).then(() => {
this.completed = true;
});
}
Por ultimo se puede añadir una barra de carga. Para esto se va hacer uso del componente mat-progress-bar de angular material para lo cual se debe importar en el app.module.
...
import { MatProgressBarModule } from '@angular/material/progress-bar';
...
imports: [
...
MatProgressBarModule,
...
],
...
Para usar el componente se añade al html de la siguiente manera:
<mat-progress-bar *ngIf="!completed" mode="determinate" value="uploadPercent | async"></mat-progress-bar>
En el app.component se añade la propiedad uploadPercent y se actualiza la función uploadFile para esto se debe importar finalize y Observable para un funcionamiento correcto.
import { finalize } from 'rxjs/operators';
import { Observable } from 'rxjs';
...
uploadFile() {
this.completed = false;
const filePath = this.file.name;
const task = this.storage.upload(filePath, this.file);
this.uploadPercent = task.percentageChanges();
task.snapshotChanges().pipe(
finalize(() => {
this.completed = true;
})
)
.subscribe();
}
```
Los archivos quedan de la siguiente manera:
app.module.ts
```javascript
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AngularFireModule } from '@angular/fire';
import { AngularFireStorageModule } from '@angular/fire/storage';
import { MatButtonModule } from '@angular/material/button';
import { FlexLayoutModule } from '@angular/flex-layout';
import { MatProgressBarModule } from '@angular/material/progress-bar';
import { AppComponent } from './app.component';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { environment } from '../environments/environment';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
BrowserAnimationsModule,
MatButtonModule,
MatProgressBarModule,
FlexLayoutModule,
AngularFireModule.initializeApp(environment.firebaseConfig),
AngularFireStorageModule,
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
```
app.component.ts
```javascript
import { Component } from '@angular/core';
import { AngularFireStorage } from '@angular/fire/storage';
import { finalize } from 'rxjs/operators';
import { Observable } from 'rxjs';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent {
file: File;
completed = false;
uploadPercent: Observable<number>;
constructor(
private storage: AngularFireStorage
){}
uploadFile() {
this.completed = false;
const filePath = this.file.name;
const task = this.storage.upload(filePath, this.file);
this.uploadPercent = task.percentageChanges();
task.snapshotChanges().pipe(
finalize(() => {
this.completed = true;
})
)
.subscribe();
}
onFileSelect(event) {
if (event.target.files.length > 0) {
this.file = event.target.files[0];
}
}
}
```
app.component.html
```html
<section fxLayout="column" fxLayoutAlign="space-around center" fxFlex="100" fxLayoutGap="20px">
<div class="label" fxFlex="30">Archivo</div>
<div fxFlex="30"><input type="file" name="file" (change)="onFileSelect($event)"/></div>
<div fxFlex="30">
<button mat-flat-button color="primary" (click)="uploadFile()">Cargar</button>
</div>
<mat-progress-bar mode="determinate" [value]="uploadPercent | async"></mat-progress-bar>
<div class="label" fxFlex="30" *ngIf="completed">Archivo cargado</div>
</section>
```
Este código se encuentra en https://github.com/plinio141/test-storage-angular
Top comments (0)