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
8 novembre 2022 à 17:20:34 - Message modéré pour le motif suivant : Merci d'utiliser le bouton code du forum pour insérer votre code


9 novembre 2022 à 3:01:32

@GeoffroyMartelée Bonsoir, merci de ne pas déterrer d'ancien sujet résolu, créer le votre en utilisant le bouton code </> de la barre d'outil du forum pour nous communiquer le code que vous avez écrit.

Déterrage

Citation des règles générales du forum :

Avant de poster un message, vérifiez la date du sujet dans lequel vous comptiez intervenir.

Si le dernier message sur le sujet date de plus de deux mois, mieux vaut ne pas répondre.
En effet, le déterrage d'un sujet nuit au bon fonctionnement du forum, et l'informatique pouvant grandement changer en quelques mois il n'est donc que rarement pertinent de déterrer un vieux sujet.

Au lieu de déterrer un sujet il est préférable :

  • soit de contacter directement le membre voulu par messagerie privée en cliquant sur son pseudonyme pour accéder à sa page profil, puis sur le lien "Ecrire un message"
  • soit de créer un nouveau sujet décrivant votre propre contexte
  • ne pas répondre à un déterrage et le signaler à la modération

Je ferme ce sujet. En cas de désaccord, me contacter par MP.

  • Partager sur Facebook
  • Partager sur Twitter