Obtenez L'URL de téléchargement du fichier chargé avec des fonctions Cloud pour Firebase

après avoir téléchargé un fichier dans le stockage Firebase avec des fonctions pour Firebase, je voudrais obtenir l'url de téléchargement du fichier.

j'ai ceci :

...

return bucket
    .upload(fromFilePath, {destination: toFilePath})
    .then((err, file) => {

        // Get the download url of file

    });

le fichier objet a beaucoup de paramètres. Même un nommé mediaLink. Cependant, si j'essaie d'accéder à ce lien, j'obtiens cette erreur :

utilisateurs Anonymes n'ont pas de stockage.objet.obtenez de l'accès à l'objet ...

<!-Est-ce que quelqu'un peut me dire comment obtenir le téléchargement public Url?

Merci

40
demandé sur Brian Burns 2017-03-22 18:35:01

10 réponses

vous devrez générer une URL signée en utilisant getSignedURL via le @google-cloud/stockage NPM module.

Exemple:

const gcs = require('@google-cloud/storage')({keyFilename: 'service-account.json'});
// ...
const bucket = gcs.bucket(bucket);
const file = bucket.file(fileName);
return file.getSignedUrl({
  action: 'read',
  expires: '03-09-2491'
}).then(signedUrls => {
  // signedUrls[0] contains the file's public URL
});

Vous aurez besoin d'initialiser @google-cloud/storagevos justificatifs d'identité de compte de service étant donné que les justificatifs d'identité par défaut ne seront pas suffisants.

UPDATE: le SDK de stockage Cloud est maintenant accessible via le SDK Admin Firebase, qui agit comme un wrapper autour de @google-cloud/stockage. Vous devrez tout de même initialiser le SDK avec un compte de service, généralement par l'intermédiaire d'une deuxième instance, non par défaut.

58
répondu James Daniels 2018-03-13 19:16:11

voici un exemple sur la façon de spécifier le token de téléchargement lors du téléchargement:

const UUID = require("uuid-v4");

const fbId = "<YOUR APP ID>";
const fbKeyFile = "./YOUR_AUTH_FIlE.json";
const gcs = require('@google-cloud/storage')({keyFilename: fbKeyFile});
const bucket = gcs.bucket(`${fbId}.appspot.com`);

var upload = (localFile, remoteFile) => {

  let uuid = UUID();

  return bucket.upload(localFile, {
        destination: remoteFile,
        uploadType: "media",
        metadata: {
          contentType: 'image/png',
          metadata: {
            firebaseStorageDownloadTokens: uuid
          }
        }
      })
      .then((data) => {

          let file = data[0];

          return Promise.resolve("https://firebasestorage.googleapis.com/v0/b/" + bucket.name + "/o/" + encodeURIComponent(file.name) + "?alt=media&token=" + uuid);
      });
}

ensuite appeler

upload(localPath, remotePath).then( downloadURL => {
    console.log(downloadURL);
  });

la chose clé ici est qu'il y a un metadata objet imbriqué dans le metadata propriété option. Réglage firebaseStorageDownloadTokens à une valeur uuid-v4 indiquera à Cloud Storage de l'utiliser comme son token d'autorisation publique.

Merci beaucoup à @martemorfosis

25
répondu Drew Beaupre 2017-11-02 15:41:35

une méthode que j'utilise avec succès est de définir une valeur UUID v4 à une clé nommée firebaseStorageDownloadTokens dans les métadonnées du fichier après qu'il a terminé le téléchargement et puis assembler L'URL de téléchargement moi-même en suivant la structure Firebase utilise pour générer ces URLs, par exemple:

https://firebasestorage.googleapis.com/v0/b/[BUCKET_NAME]/o/[FILE_PATH]?alt=media&token=[THE_TOKEN_YOU_CREATED]

Je ne sais pas combien "sûr" est d'utiliser cette méthode (étant donné que Firebase pourrait changer la façon dont il génère les URLs de téléchargement dans le futur ) mais il est facile à mettre en œuvre.

10
répondu martemorfosis 2017-04-03 23:15:06

For those wondering where the Firebase Admin SDKSERVICEACCOUNTKEY.le dossier json devrait partir. Il suffit de le placer dans le dossier fonctions et de les déployer comme d'habitude.

il me déconcerte encore pourquoi nous ne pouvons pas simplement obtenir l'url de téléchargement à partir des métadonnées comme nous le faisons dans le SDK Javascript. Générer une url qui finira par expirer et la sauvegarder dans la base de données n'est pas souhaitable.

8
répondu Clinton 2017-04-26 15:00:44

Avec les récents changements dans les fonctions objet réponse, vous pouvez obtenir tout ce dont vous avez besoin pour "piquer" ensemble, l'URL de téléchargement comme suit:

 const img_url = 'https://firebasestorage.googleapis.com/v0/b/[YOUR BUCKET]/o/'
+ encodeURIComponent(object.name)
+ '?alt=media&token='
+ object.metadata.firebaseStorageDownloadTokens;

console.log('URL',img_url);
8
répondu Demian S 2018-04-18 02:02:59

désolé mais je ne peux pas poster un commentaire à votre question ci-dessus en raison de la réputation manquante, donc je l'inclurai dans cette réponse.

faire comme indiqué ci-dessus en générant une Url signée, mais au lieu d'utiliser le compte de service.json je pense que vous devez utiliser le serviceAccountKey.json que vous pouvez générer à (remplacer VOTREPROJETTID par conséquent)

https://console.firebase.google.com/project/YOURPROJECTID/settings/serviceaccounts/adminsdk

Exemple:

const gcs = require('@google-cloud/storage')({keyFilename: 'serviceAccountKey.json'});
// ...
const bucket = gcs.bucket(bucket);
// ...
return bucket.upload(tempLocalFile, {
        destination: filePath,
        metadata: {
          contentType: 'image/jpeg'
        }
      })
      .then((data) => {
        let file = data[0]
        file.getSignedUrl({
          action: 'read',
          expires: '03-17-2025'
        }, function(err, url) {
          if (err) {
            console.error(err);
            return;
          }

          // handle url 
        })
6
répondu NiVeK92 2017-03-23 09:36:07

je suggère d'utiliser l'option predefinedAcl: 'publicRead' lors du téléchargement d'un fichier avec Stockage Dans Le Cloud NodeJS 1.6.x:

const options = {
    destination: yourFileDestination,
    predefinedAcl: 'publicRead'
};

bucket.upload(attachment, options);

alors, obtenir L'URL publique est aussi simple que:

bucket.upload(attachment, options).then(result => {
    const file = result[0];
    return file.getMetadata();
}).then(results => {
    const metadata = results[0];
    console.log('metadata=', metadata.mediaLink);
}).catch(error => {
    console.error(error);
});
4
répondu Laurent 2018-03-21 16:03:31

cela fonctionne si vous avez juste besoin d'un fichier public avec une URL simple. Notez que cela peut annuler les règles de stockage de la base de données.

bucket.upload(file, function(err, file) {
    if (!err) {
      //Make the file public
      file.acl.add({
      entity: 'allUsers',
      role: gcs.acl.READER_ROLE
      }, function(err, aclObject) {
          if (!err) {
              var URL = "https://storage.googleapis.com/[your bucket name]/" + file.id;
              console.log(URL);
          } else {
              console.log("Failed to set permissions: " + err);
          }
      });  
    } else {
        console.log("Upload failed: " + err);
    }
});
1
répondu Dakine 2018-01-14 13:18:55

Je ne peux pas commenter la réponse de James Daniels, mais je pense que c'est très Important à lire.

donner une URL signée comme il l'a fait semble pour beaucoup de cas assez mauvais et possible Dangereux. Selon la documentation de Firebase l'url signée expire après un certain temps, donc en ajoutant cela à votre base de données vous obtiendrez une url vide après un certain délai

il se peut que vous ayez mal compris la Documentation et l'url signée. ça n'expire pas, ce qui aurait des problèmes de sécurité. La Clé semble être la même pour chaque fichier téléchargé. Cela signifie qu'une fois que vous avez l'url d'un fichier, quelqu'un pourrait facilement accéder aux fichiers qu'il n'est pas censé accéder, simplement en connaissant leurs noms.

si je n'avais pas compris, j'aurais dû être corrigé. Sinon, quelqu'un devrait probablement mettre à jour la solution susmentionnée. Si j'ai peut-être tort, il y a

1
répondu Renji 2018-04-30 21:09:07

pour ceux qui utilisent Firebase SDK etadmin.initializeApp:

1 - générer une clé privée et le placer dans /dossier fonctions.

2 - Configurez votre code comme suit:

const serviceAccount = require('../../serviceAccountKey.json');
try { admin.initializeApp(Object.assign(functions.config().firebase, { credential: admin.credential.cert(serviceAccount) })); } catch (e) {}

Documentation

Le try/catch est parce que je suis à l'aide d'un index.js que les importations d'autres fichiers et crée une fonction pour chaque fichier. Si vous utilisez un seul index.fichier js avec toutes les fonctions, vous devriez être ok avec admin.initializeApp(Object.assign(functions.config().firebase, { credential: admin.credential.cert(serviceAccount) }));.

0
répondu Allan Poppe 2018-05-18 19:02:54