Partage
  • Partager sur Facebook
  • Partager sur Twitter

Cours Angular/Firebase problème Storage

Sujet résolu
    31 mai 2018 à 15:11:33

    Bonjour à tous,

    Je suis actuellement le cours "Développez des applications web avec Angular" et je bloque à la dernière partie "Créer une application complète avec Angular et Firebase".

    Je suis arrivé à l'étape de l'API Firebase Storage afin de permettre à l'utilisateur d'ajouter une photo et d'afficher celle-ci dans (SingleBookComponent) qui est nommé (SingleDrumComponent) pour ma part.

    J'arrive bien à ajouter la photo celle-ci est bien enregistré dans Firebase mais je n'arrive pas à l'afficher dans (SingleBookComponent)

    Drums.service.ts
    
    
    
    import { Injectable } from '@angular/core';
    import { Drum } from '../models/Drum.model';
    import { Subject } from 'rxjs';
    import * as  firebase from 'firebase';
    import Datasnapshot = firebase.database.DataSnapshot;
    
    @Injectable({
      providedIn: 'root'
    })
    export class DrumsService {
    
      drums: Drum[] = [];
      drumsSubject = new Subject<Drum[]>();
    
      constructor() { }
    
      emitDrums() {
        this.drumsSubject.next(this.drums);
      }
    
      saveDrums() {
          firebase.database().ref('/drums').set(this.drums);
      }
    
      getDrums() {
          firebase.database().ref('/drums')
            .on('value', (data: Datasnapshot) => {
              this.drums = data.val() ? data.val() : [];
              this.emitDrums();
            });
      }
    
      getSingleDrum(id: number) {
          return new Promise(
            (resolve, reject) => {
              firebase.database().ref('/drums/' + id).once('value').then(
                (data: Datasnapshot) => {
                  resolve(data.val());
                }, (error) => {
                  reject(error);
                }
              );
            }
          );
        }
    
      createNewDrum(newDrum: Drum) {
          this.drums.push(newDrum);
          this.saveDrums();
          this.emitDrums();
      }
    
      removeDrum(drum: Drum) {
        
        if(drum.photo) {
          const storageRef = firebase.storage().refFromURL(drum.photo);
          storageRef.delete().then(
            () => {
              console.log('Photo removed!');
            },
            (error) => {
              console.log('Could not remove photo! : ' + error);
            }
          );
        }
        const drumIndexToRemove = this.drums.findIndex(
          (drumEl) => {
                if(drumEl === drum) {
                  return true;
                }
          }
        );
        this.drums.splice(drumIndexToRemove, 1);
        this.saveDrums();
        this.emitDrums();
      }
      
      uploadFile(file: File) {
        return new Promise (
          (resolve, reject) => {
            const almostUniqueFileName = Date.now().toString();
            const upload = firebase.storage().ref()
                .child('images/' + almostUniqueFileName + file.name).put(file);
              upload.on(firebase.storage.TaskEvent.STATE_CHANGED,
                () => {
                  console.log('Chargement…');
                },
                (error) => {
                  console.log('Erreur de chargement ! : ' + error);
                  reject();
                },
                () => {
                  resolve(upload.snapshot.downloadURL);
                }
              );
          }
        );
      }
    }
    
    drum-form.component.ts
    
    import { Component, OnInit } from '@angular/core';
    import { FormBuilder, FormGroup, Validators } from '@angular/forms';
    import { Drum } from '../../models/Drum.model';
    import { DrumsService } from '../../services/drums.service';
    import { Router } from '@angular/router';
    
    @Component({
      selector: 'app-drum-form',
      templateUrl: './drum-form.component.html',
      styleUrls: ['./drum-form.component.css']
    })
    export class DrumFormComponent implements OnInit {
    
      drumForm: FormGroup;
      fileIsUploading = false;
      fileUrl: string;
      fileUploaded = false;
    
      constructor(private formBuilder: FormBuilder, private drumsService: DrumsService,
                  private router: Router) { }
                  
      ngOnInit() {
        this.initForm();
      }
      
      initForm() {
        this.drumForm = this.formBuilder.group({
          title: ['', Validators.required],
          author: ['', Validators.required],
          detail: ''
        });
      }
      
      onSaveDrum() {
        const title = this.drumForm.get('title').value;
        const author = this.drumForm.get('author').value;
        const detail = this.drumForm.get('detail').value;
        const newDrum = new Drum(title, author, detail);
        if(this.fileUrl && this.fileUrl !== '') {
          newDrum.photo = this.fileUrl;
        }
        this.drumsService.createNewDrum(newDrum);
        this.router.navigate(['/drums']);
      }
    
      onUploadFile(file: File) {
        this.fileIsUploading = true;
        this.drumsService.uploadFile(file).then(
          (url: string) => {
            this.fileUrl = url;
            this.fileIsUploading = false;
            this.fileUploaded = true;
          }
        );
    }
    detectFiles(event) {
      this.onUploadFile(event.target.files[0]);
      }
    }
    
    
    single-drum.component.html
    <div class="row">
      <div class="col-xs-12">
          <img style="max-width:400px;" *ngIf="drum.photo" [src]="drum.photo">
        <h1>{{ drum.title }}</h1>
        <h3><span>Publié par :</span>  {{ drum.author }}</h3>
        <p>{{ drum.detail }}</p>
        <button class="btn btn-default" (click)="onBack()">Retour</button>
      </div>
    </div>

    Merci d'avance pour votre aide ! 

    • Partager sur Facebook
    • Partager sur Twitter
      7 juin 2018 à 16:28:54

      Update : 

      Après recherches et analyses, il semble que c'est au niveau de cette fonction que ça ne fonctionne pas :

      uploadFile(file: File) {
          return new Promise(
            (resolve, reject) => {
              const almostUniqueFileName = Date.now().toString();
              const upload = firebase.storage().ref()
                .child('images/' + almostUniqueFileName + file.name).put(file);
              upload.on(firebase.storage.TaskEvent.STATE_CHANGED,
                () => {
                  console.log('Chargement…');
                },
                (error) => {
                  console.log('Erreur de chargement ! : ' + error);
                  reject();
                },
                () => {
                  resolve(upload.snapshot.downloadURL);
                }
              );
            }
          );
      }

      (file : File) est bien reçu, la définition d'upload fonctionne.

      En revanche, la troisième fonction :

                () => {
                  resolve(upload.snapshot.downloadURL);
                }

      Celle-ci renvoie "undefined", ce qui fait qu'à la réception supposée "d'url" dans books.service, aucune valeur n'est reçu, derrière ça fait que rien n'est sauvegardé dans la BDD


      -
      Edité par XavierMinard1 8 juin 2018 à 10:48:03

      • Partager sur Facebook
      • Partager sur Twitter
        9 juin 2018 à 20:54:13

        J'ai le même problème et j'ai fait le même constat que toi, l'url est non définie...

        Du coup dans la bdd le livre est enregistré sans photo...

        Quelqu'un pour nous orienter ?

        --------

        En cherchant un peu dans la doc de firebase, j'ai trouvé ça :

        https://firebase.google.com/docs/storage/web/upload-files

        J'ai modifié la fonction de la promise par :

        resolve(upload.snapshot.ref.getDownloadURL());

        et ça fonctionne :-), ça devrait fonctionner pour toi aussi...

        Bon courage !

        -
        Edité par Magali1981 9 juin 2018 à 21:15:26

        • Partager sur Facebook
        • Partager sur Twitter
          11 juin 2018 à 9:01:13

          Roh ! Merci ! 

          Il me manquait les "()" dans la syntaxe du getDownloadURL (pour beaucoup ça semble couler de source quand tu vois les forums) 

          Tout fonctionne (enfin) à merveille ! WOOT ! 

          • Partager sur Facebook
          • Partager sur Twitter
            24 juin 2018 à 18:37:26

            Effectivement ça fonctionne également de mon coté.

            Merci à toi ! 

            • Partager sur Facebook
            • Partager sur Twitter
              23 juillet 2018 à 8:56:33

              Ah super merci Magali1981. Moi j'avais un problème de "deprecated". Et dans une note il mettait : @deprecated
                   * Use Reference.getDownloadURL instead. This property will be removed in a
                   * future release.

              Et je ne comprenais pas comment utiliser ce Reference. Mais maintenant ça fonctionne. Tout fonctionne !

              -
              Edité par Wawan_ns 23 juillet 2018 à 8:56:59

              • Partager sur Facebook
              • Partager sur Twitter
                4 août 2018 à 16:34:58

                Ca fait 2 jours que je butais là desssus... Merci beaucoup !
                • Partager sur Facebook
                • Partager sur Twitter
                  8 août 2018 à 17:40:14

                  Merci, je bloquais aussi, une petite mise à jour du cours serait la bienvenue ;-)
                  • Partager sur Facebook
                  • Partager sur Twitter
                    11 octobre 2018 à 23:12:42

                    Merci, je mets la fonction complète pour ceux qui galère encore :-)
                    uploadFile(file: File) {
                      return new Promise(
                        (resolve, reject) => {
                          const almostUniqueFileName = Date.now().toString();
                          const upload = firebase.storage().ref()
                            .child('images/' + almostUniqueFileName + file.name).put(file);
                          upload.on(firebase.storage.TaskEvent.STATE_CHANGED,
                            () => {
                              console.log('Chargement…');
                            },
                            (error) => {
                              console.log('Erreur de chargement ! : ' + error);
                              reject();
                            },
                            () => {
                              resolve(upload.snapshot.ref.getDownloadURL());
                            }
                          );
                        }
                      );
                    }

                    -
                    Edité par ---DAms---- 11 octobre 2018 à 23:16:35

                    • Partager sur Facebook
                    • Partager sur Twitter
                      30 octobre 2018 à 17:04:05

                      Merci beaucoup Magali !

                      -
                      Edité par Daniel EVRARD Fb 30 octobre 2018 à 17:08:00

                      • Partager sur Facebook
                      • Partager sur Twitter
                        13 novembre 2018 à 12:09:38

                        Merci ! 

                        Cela faisait 2 jours aussi que je bloquais dessus

                        Vive Magali ;-)

                        • Partager sur Facebook
                        • Partager sur Twitter
                          2 décembre 2018 à 19:37:19

                          Merci beaucoup, problème résolu également ;-) +1 pour Magali1981 !!
                          • Partager sur Facebook
                          • Partager sur Twitter
                          MN¨
                            5 décembre 2018 à 12:52:46

                            Bonjour,

                            il y a aussi une autre possibilité, en plus du code du cours qui n'est plus le bon,

                            l'autorisation de storage n'aurait pas été donnée dans firebase, dans ce cas, vous verriez une erreur sans pouvoir la définir

                            dans la première partie de la promesse, si vous modifiez:

                            () => {
                                      console.log('Chargement…');
                                      upload.snapshot.ref.getDownloadURL().then(function(downloadURL) {
                                console.log('File available at', downloadURL);
                              });

                            vous pourriez voir cette erreur mieux décrite dans la console

                            Object { code_: "storage/unknown", message_: "Firebase Storage: An unknown error occurred, please check the error payload for server response.", serverResponse_: "{\n \"error\": {\n \"code\": 400,\n \"message\": \"Permission denied. Could not access bucket bookshelves-3d2cb.appspot.com. Please enable Firebase Storage for your bucket by visiting the Storage tab in the Firebase Console and ensure that you have sufficient permission to properly provision resources.\"\n }\n}", name_: "FirebaseError" }


                            pour solutionner le problème

                            dans la console firebase > développer > Storage > commencer une nouvelle DB > définir les règles de sécurité

                            les règles par défaut seront les bonnes

                            • Partager sur Facebook
                            • Partager sur Twitter
                              30 janvier 2019 à 21:47:38

                              Pour les jusqueboutistes, la fonction getDownloadURL() attend le retour du serveur pour fournir l'URL. Si on veut pouvoir manipuler la string dans la partie "complete" d'upload.on, on peut aussi faire comme ceci :

                                        () => {
                                          upload.snapshot.ref.getDownloadURL().then(
                                            (downloadUrl) => {
                                              console.log('Upload successful! ('+downloadUrl+')');
                                              resolve(downloadUrl);
                                            }
                                          );
                                        }
                              

                              Ainsi, on peut afficher l'URL dans la console par exemple.

                              Attention a bien mettre le resolve dans le then et pas en dehors, sinon on exécute le code avant l'arrivée de l'info du serveur et du coup on se retrouve avec undefined à nouveau. j'ai mis un  moment à comprendre cette subtilité...

                              -
                              Edité par raphaelmollon 30 janvier 2019 à 21:48:20

                              • Partager sur Facebook
                              • Partager sur Twitter
                                15 mars 2019 à 17:25:53

                                Bonjour à tous,

                                Malgré les conseils donnés dans ce poste, j'ai toujours un soucis concernant le fonctionnement de l'upload de l'image.

                                J'ai ouvert un poste non résolu en relation connexe à ce sujet.

                                https://openclassrooms.com/forum/sujet/cours-angular-firebase-probleme-sur-lupload

                                Je vous remercie d'avance de votre aide et vous souhaites une agréable journée.

                                -
                                Edité par radiance63 15 mars 2019 à 17:48:01

                                • Partager sur Facebook
                                • Partager sur Twitter
                                Never trust user input.
                                  12 octobre 2019 à 15:35:23

                                  Merci à Magali, ça m'a beaucoup aidé aussi.

                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                    26 août 2020 à 17:48:58

                                    Salut à tous

                                    Voilà je développe une application web avec Angular et Firebase.

                                    Dans la page d'accueil de mon application web je dois afficher en carrousel des images stockées dans storage de firebase.

                                    Les images sont stockées dans un dossier ("images/carrousel/") sur storage.

                                    Mon souci est de récupérer dans une liste (array de type string) les différentes urls des images stockées. ????

                                    Notez bien que selon le script je ne connais pas les noms des différentes images stockées, puisque les images seront changées dans le temps et je n'aimerais pas à vouloir changer à chaque fois le script lorsque j'aurais à ajouter une nouvelle image ou à en supprimer.

                                    • Partager sur Facebook
                                    • Partager sur Twitter
                                    Ted-Dide

                                    Cours Angular/Firebase problème Storage

                                    × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                    × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                                    • Editeur
                                    • Markdown