0
votes

Can someone guide me to upload multiple images to Firebase at the same time?

What I'm trying to do is upload several images to Firebase Storage and save each reference in Firestore (in an array, for example). I have managed to do it but only with one image. I am using Angularfire Storage.

Here a stackblitz if you want to see it in detail: https://stackblitz.com/edit/upload-multiple-firebase

At this moment the aspect is the following:

In Storage it looks like this (note that the image is inside a folder with the same Firestore ID): enter image description here

In Firestore it looks like this (note that the ID is the same as in Storage): enter image description here

Here my code:

component.ts

import { Component, OnInit, ViewChild  } from '@angular/core';
import { finalize } from 'rxjs/operators';
import { AngularFireStorage } from 'angularfire2/storage';
import { AngularFirestore } from 'angularfire2/firestore';
import { Observable } from 'rxjs';
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
import { FirebaseService } from './services/firebase.service';

export interface Test {
  imagenDestacada: string;
}

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent implements OnInit  {

uploadPercent: Observable<number>;
downloadURL: Observable<string>;
selectedFile: FileList | null;
forma: FormGroup;
tests: Observable<any[]>;

constructor(fb: FormBuilder, private storage: AngularFireStorage, private afs: AngularFirestore, private fs: FirebaseService ) { 
this.forma = fb.group ({
  categoria: ['myCategoria'],

})
}
ngOnInit() {
  this.mostrarImagenes();
}

detectFiles(event) {
  this.selectedFile = event.target.files[0];
}

uploadFile() {
  const myTest = this.afs.collection('test').ref.doc();
  console.log(myTest.id)

  const file = this.selectedFile
  const filePath = `${myTest.id}/name1`;
  const fileRef = this.storage.ref(filePath);
  const task = this.storage.upload(filePath, file);

  this.uploadPercent = task.percentageChanges();  

  task.snapshotChanges().pipe(
    finalize(() => {
      fileRef.getDownloadURL().toPromise().then( (url) => {
        this.downloadURL = url;

        myTest.set({
          categoria: this.forma.value.categoria,
          imagenes : this.downloadURL,
          myId : myTest.id
        })

        console.log( this.downloadURL ) 
      }).catch(err=> { console.log(err) });
    })    
  )
  .subscribe()
}

mostrarImagenes() {
  this.tests = this.fs.getTests();
}

}

component.html

<div class="container py-4">

  <input type="file" multiple (change)="detectFiles($event)">
  <button (click)="uploadFile()" class="btn btn-primary">UPLOAD</button>
  <div>{{ uploadPercent | async }}</div>
  <a [href]="downloadURL">{{ downloadURL }}</a>

  <hr>
  <div class="row">
    <div class="col-lg-2 col-6" *ngFor="let test of tests | async">
      <div class="card">
        <img class="card-img-top" src="{{ test.imagenes }}" width="100%">
        <div class="card-body">
        <p class="card-text">My text</p>
      </div>
    </div>
  </div>
</div>

</div>

service.ts

import { Injectable } from '@angular/core';
import { AngularFirestore } from 'angularfire2/firestore';
import { Observable } from 'rxjs';

@Injectable()
export class FirebaseService {

tests: Observable<any[]>;

constructor( private afs: AngularFirestore ) { }

getTests() {
  this.tests = this.afs.collection('test').valueChanges();
  return this.tests;
}

}
1

1 Answers

0
votes

Because your detectFiles only set to detect 1 file.

  1. Change it to handle all the selected file instead of file[0] only.
  2. Change selectedFile to selectedFileList array instead.
  3. Change uploadFile logic to loop through the selectedFileList and upload.