Firebase için Cloud Functions ile yüklenen dosyadan İndirme URL'sini alın


125

Functions for Firebase ile Firebase Storage'a bir dosya yükledikten sonra, dosyanın indirme url'sini almak istiyorum.

Bu bende var :

...

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

        // Get the download url of file

    });

Nesne dosyasında birçok parametre vardır. Hatta bir isim mediaLink. Ancak, bu bağlantıya erişmeye çalışırsam şu hatayı alıyorum:

Anonim kullanıcılar, storage.objects.get erişimine sahip değildir ...

Biri bana genel indirme URL'sini nasıl alacağımı söyleyebilir mi?

teşekkür ederim


Ayrıca bkz Bu yayını fonksiyonu mevcut verilerden URL'yi yeniden yapılandırır.
Kato

Yanıtlar:


133

@ Google-cloud / storage NPM modülü aracılığıyla getSignedURL kullanarak imzalanmış bir URL oluşturmanız gerekir .

Misal:

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
});

Sen ilklendirmelisiniz @google-cloud/storageile servis hesap kimlik uygulaması varsayılan kimlik bilgileri yeterli olmayacağından.

GÜNCELLEME : Cloud Storage SDK'ya artık @ google-cloud / storage etrafında bir sarmalayıcı görevi gören Firebase Admin SDK aracılığıyla erişilebilir . Bunun tek yolu şudur:

  1. SDK'yı, genellikle varsayılan olmayan ikinci bir örnek üzerinden özel bir hizmet hesabıyla başlatın.
  2. Veya bir hizmet hesabı olmadan, varsayılan App Engine hizmet hesabına "signBlob" izni vererek.

75
Bu tuhaf. Firebase Android, iOS ve Web SDK'yı kullanırken, İndirme URL'sini bir Depolama referansından kolayca alabiliriz. Yönetici iken neden bu kadar kolay değil? Not: gcs'yi başlatmak için gereken 'service-account.json'u nerede bulabilirim?
Valentin

2
Bunun nedeni, admin-sdk'nin herhangi bir Cloud Storage eklentisine sahip olmamasıdır. Admin-sdk hizmet hesabınızı json buradan alabilirsiniz console.firebase.google.com/project/_/settings/serviceaccounts/…
James Daniels

18
Bu yöntemle oluşturulan URL gülünç derecede uzun. @Martemorfosis tarafından önerilen yöntemle oluşturulan URL çok daha iyidir. Bu URL'yi üreten herhangi bir işlev var mı? Firebase-sdk kullanırken gelecekte kullanmak için veritabanına kaydettiğim şey bu. Functions etki alanında bir yansıtma yönteminin bulunması gerekir.
Bogac

3
Dağıtılan işlevler boyunca service-account.json dosyasını nasıl yükleyebiliriz? Bunu işlevler klasörüne yerleştirmeyi ve package.json'daki dosya alanına referans vermeyi denedim, ancak dağıtılmıyor. Teşekkür ederim.
David Aroesti

2
Eklemek gerekir mi actionve expires?
Chad Bingham

83

İndirme jetonunun yüklemede nasıl belirleneceğine ilişkin bir örnek:

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);
      });
}

sonra ara

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

Buradaki kilit nokta metadata, metadataoption özelliği içinde yuvalanmış bir nesnenin olmasıdır . firebaseStorageDownloadTokensBir uuid-v4 değerine ayarlamak , Cloud Storage'a bunu genel kimlik doğrulama jetonu olarak kullanmasını söyler.

@ Martemorfosis'e çok teşekkürler


Depolamaya zaten yüklenmiş olan bir dosya için geçerli bir UUID belirtecini nasıl edinebilirim? Rastgele UUID oluşturmak yardımcı olmadı. Herhangi bir işaret var mı?
DerFaizio

3
Cevabı @martemorfosis gönderisinde buldum. UUID, object.metadata export.uploadProfilePic = functions.storage.object (). OnChange (event => {const object = event.data; // Storage nesnesi. Const uuid = object.metadata.firebaseStorageDownloadTokens; // ...
DerFaizio

Kova örneği için teşekkürler! Yaklaşık 1 saat boyunca kova ve
eğeleme

1
Cevabınız için teşekkürler! Benim durumumda, yükleme bittiğinde veri döndürmeyen buck.file (fileName) .createWriteStream ile yüklüyordum, sonuç olarak encodeURIComponent (file.name) yerine encodeURIComponent (fileName) kullandım.
Stanislau Buzunko

2
Bu doğru cevap olmalı. Firebase SDK'ları (@DevMike) tarafından oluşturulan URL'ye benzer bir URL ile sonuçlanır ve tam olarak perde arkasında yaptıklarına bahse girerim.
Samuel E.

66

Bu cevap, Google / Firebase Bulut Depolama'ya bir dosya yüklerken indirme URL'sini alma seçeneklerini özetleyecektir. Üç tür indirme URL'si vardır:

  1. geçici olan ve güvenlik özelliklerine sahip imzalı indirme URL'leri
  2. Kalıcı olan ve güvenlik özelliklerine sahip olan simge indirme URL'leri
  3. kalıcı olan ve güvenliği olmayan genel indirme URL'leri

Belirteç indirme URL'si almanın üç yolu vardır. Diğer iki indirme URL'sinin bunları almanın tek bir yolu vardır.

Firebase Storage Console'dan

İndirme URL'sini Firebase Storage konsolundan alabilirsiniz:

görüntü açıklamasını buraya girin

İndirme URL'si şuna benzer:

https://firebasestorage.googleapis.com/v0/b/languagetwo-cd94d.appspot.com/o/Audio%2FEnglish%2FUnited_States-OED-0%2Fabout.mp3?alt=media&token=489c48b3-23fb-4270-bd85-0a328d2808e5

İlk bölüm, dosyanıza giden standart bir yoldur. Sonunda jeton var. Bu indirme URL'si kalıcıdır, yani iptal etmenize rağmen süresi dolmaz.

getDownloadURL () Ön Uçtan

Dokümantasyon kullanımına söyler getDownloadURL():

let url = await firebase.storage().ref('Audio/English/United_States-OED-' + i +'/' + $scope.word.word + ".mp3").getDownloadURL();

Bu, Firebase Storage konsolunuzdan alabileceğiniz indirme URL'sinin aynısını alır. Bu yöntem kolaydır, ancak nispeten basit bir veritabanı yapısı için uygulamamda yaklaşık 300 satır kod olan dosyanızın yolunu bilmenizi gerektirir. Veritabanınız karmaşıksa, bu bir kabus olur. Ve ön uçtan dosyalar yükleyebilirsiniz, ancak bu, kimlik bilgilerinizi uygulamanızı indiren herkese ifşa eder. Dolayısıyla, çoğu proje için dosyalarınızı Node arka ucunuzdan veya Google Cloud Functions'dan yüklemek, ardından indirme URL'sini almak ve dosyanızla ilgili diğer verilerle birlikte veritabanınıza kaydetmek isteyeceksiniz.

Geçici İndirme URL'leri için getSignedUrl ()

getSignedUrl () , bir Node arka ucundan veya Google Cloud Functions'tan kolayca kullanılabilir:

  function oedPromise() {
    return new Promise(function(resolve, reject) {
      http.get(oedAudioURL, function(response) {
        response.pipe(file.createWriteStream(options))
        .on('error', function(error) {
          console.error(error);
          reject(error);
        })
        .on('finish', function() {
          file.getSignedUrl(config, function(err, url) {
            if (err) {
              console.error(err);
              return;
            } else {
              resolve(url);
            }
          });
        });
      });
    });
  }

İmzalı bir indirme URL'si şuna benzer:

https://storage.googleapis.com/languagetwo-cd94d.appspot.com/Audio%2FSpanish%2FLatin_America-Sofia-Female-IBM%2Faqu%C3%AD.mp3?GoogleAccessId=languagetwo-cd94d%40appspot.gserviceaccount.com&Expires=4711305600&Signature=WUmABCZIlUp6eg7dKaBFycuO%2Baz5vOGTl29Je%2BNpselq8JSl7%2BIGG1LnCl0AlrHpxVZLxhk0iiqIejj4Qa6pSMx%2FhuBfZLT2Z%2FQhIzEAoyiZFn8xy%2FrhtymjDcpbDKGZYjmWNONFezMgYekNYHi05EPMoHtiUDsP47xHm3XwW9BcbuW6DaWh2UKrCxERy6cJTJ01H9NK1wCUZSMT0%2BUeNpwTvbRwc4aIqSD3UbXSMQlFMxxWbPvf%2B8Q0nEcaAB1qMKwNhw1ofAxSSaJvUdXeLFNVxsjm2V9HX4Y7OIuWwAxtGedLhgSleOP4ErByvGQCZsoO4nljjF97veil62ilaQ%3D%3D

İmzalanmış URL'nin bir son kullanma tarihi ve uzun bir imzası vardır. Gsutil signurl -d komut satırına ilişkin belgeler , imzalı URL'lerin geçici olduğunu belirtir: varsayılan süre sonu bir saattir ve maksimum süre sonu yedi gündür.

Burada getSignedUrl imzalı URL'nizin bir hafta içinde süresinin dolacağını asla söylemediğini söyleyeceğim . Dokümantasyon kodunun 3-17-2025son kullanma tarihi vardır ve bu, gelecekte sona erme yıllarını ayarlayabileceğinizi gösterir. Uygulamam mükemmel çalıştı ve bir hafta sonra çöktü. Hata mesajı, indirme URL'sinin süresinin dolduğunu değil, imzaların eşleşmediğini söylüyordu. Kodumda çeşitli değişiklikler yaptım ve her şey çalıştı ... hepsi bir hafta sonra çökene kadar. Bu bir aydan fazla bir hayal kırıklığı ile devam etti.

Dosyanızı Herkese Açık Hale Getirin

Dosyanızdaki izinleri belgelerde açıklandığı gibi herkese açık olarak ayarlayabilirsiniz . Bu, Bulut Depolama Tarayıcınızdan veya Düğüm sunucunuzdan yapılabilir. Bir dosyayı genel veya bir dizini veya tüm Depolama veritabanınızı yapabilirsiniz. Düğüm kodu şöyledir:

var webmPromise = new Promise(function(resolve, reject) {
      var options = {
        destination: ('Audio/' + longLanguage + '/' + pronunciation + '/' + word + '.mp3'),
        predefinedAcl: 'publicRead',
        contentType: 'audio/' + audioType,
      };

      synthesizeParams.accept = 'audio/webm';
      var file = bucket.file('Audio/' + longLanguage + '/' + pronunciation + '/' + word + '.webm');
      textToSpeech.synthesize(synthesizeParams)
      .then(function(audio) {
        audio.pipe(file.createWriteStream(options));
      })
      .then(function() {
        console.log("webm audio file written.");
        resolve();
      })
      .catch(error => console.error(error));
    });

Sonuç, Bulut Depolama Tarayıcınızda şöyle görünecektir:

görüntü açıklamasını buraya girin

Dosyanızı indirmek için herkes standart yolu kullanabilir:

https://storage.googleapis.com/languagetwo-cd94d.appspot.com/Audio/English/United_States-OED-0/system.mp3

Bir dosyayı genel yapmanın başka bir yolu da makePublic () yöntemini kullanmaktır . Bunu çalıştırmayı başaramadım, kova ve dosya yollarını doğru bir şekilde almak zor.

İlginç bir alternatif, Erişim Kontrol Listelerini kullanmaktır . Bir dosyayı yalnızca bir listeye koyduğunuz kullanıcılar için kullanılabilir authenticatedReadhale getirebilir veya dosyayı bir Google hesabından oturum açmış herkesin kullanımına sunabilirsiniz. "Firebase Auth kullanarak uygulamama giriş yapan herkes" seçeneği olsaydı, erişimi yalnızca kullanıcılarımla sınırlayacağı için bunu kullanırdım.

FirebaseStorageDownloadTokens ile Kendi İndirme URL'nizi Oluşturun

Birkaç yanıt, belgelenmemiş bir Google Storage nesnesi özelliğini tanımlar firebaseStorageDownloadTokens. Bununla Storage'a kullanmak istediğiniz jetonu söyleyebilirsiniz. uuidNode modülü ile bir token oluşturabilirsiniz . Dört satır kod ve kendi indirme URL'nizi, konsoldan aldığınız indirme URL'sini veya getDownloadURL(). Dört satır kod şunlardır:

const uuidv4 = require('uuid/v4');
const uuid = uuidv4();
metadata: { firebaseStorageDownloadTokens: uuid }
https://firebasestorage.googleapis.com/v0/b/" + bucket.name + "/o/" + encodeURIComponent('Audio/' + longLanguage + '/' + pronunciation + '/' + word + '.webm') + "?alt=media&token=" + uuid);

Kod bağlamında şöyledir:

var webmPromise = new Promise(function(resolve, reject) {
  var options = {
    destination: ('Audio/' + longLanguage + '/' + pronunciation + '/' + word + '.mp3'),
    contentType: 'audio/' + audioType,
    metadata: {
      metadata: {
        firebaseStorageDownloadTokens: uuid,
      }
    }
  };

      synthesizeParams.accept = 'audio/webm';
      var file = bucket.file('Audio/' + longLanguage + '/' + pronunciation + '/' + word + '.webm');
      textToSpeech.synthesize(synthesizeParams)
      .then(function(audio) {
        audio.pipe(file.createWriteStream(options));
      })
      .then(function() {
        resolve("https://firebasestorage.googleapis.com/v0/b/" + bucket.name + "/o/" + encodeURIComponent('Audio/' + longLanguage + '/' + pronunciation + '/' + word + '.webm') + "?alt=media&token=" + uuid);
      })
      .catch(error => console.error(error));
});

Bu bir yazım hatası değil - firebaseStorageDownloadTokensçift ​​katman halinde yuvalanmanız gerekiyor metadata:!

Doug Stevenson firebaseStorageDownloadTokens, bunun resmi bir Google Bulut Depolama özelliği olmadığına dikkat çekti . Herhangi bir Google belgesinde bulamayacaksınız ve gelecekteki sürümünde olacağına dair bir söz yok @google-cloud. Seviyorum firebaseStorageDownloadTokensçünkü istediğimi elde etmenin tek yolu bu, ama güvenli olmadığı bir "kokusu" var.

Neden Node'dan getDownloadURL () yok?

@Clinton'ın yazdığı gibi, Google file.getDownloadURL()bir yöntem oluşturmalıdır @google-cloud/storage(yani, Düğüm arka ucunuz ). Google Cloud Functions'tan bir dosya yüklemek ve jeton indirme URL'sini almak istiyorum.


11
Bunun @google-cloud/storageiçin bir sorun oluşturdum , + 1'lemekten
Théo Champion

1
son makePublic () bağlantısı.
galki

1
Görünüşe göre firebaseStorageDownloadTokensartık çalışmıyor.
Mason

1
Kabul edilen yanıt, süresi dolmayan ve doğru olmayan kalıcı bir indirme URL'si almanın mümkün olmadığını gösteriyor. Cevabınızdaki detay mükemmel ve doğru cevap olarak işaretlenmelidir. Teşekkür ederim.
DevMike

2
@thomas harika özet için teşekkürler! Kalıcı bir jeton indirme URL'si almanın 3 yolu olduğundan bahsettiniz, ancak yalnızca 2'sini paylaştınız: (a) Firebase Storage Console'dan ve (b) getDownloadURL () Ön Uçtan. 3. yol ne acaba?
czphilip

23

Nesne yanıtı işlevlerindeki son değişikliklerle , indirme URL'sini aşağıdaki gibi "birleştirmek" için ihtiyacınız olan her şeyi elde edebilirsiniz:

 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);

2
Nesne yanıtına mı atıfta bulunuyorsunuz bucket.file().upload()? Yanıt verilerinde herhangi bir meta veri özelliği almıyorum ve bunları nasıl elde edeceğimi bilmiyorum firebaseStorageDownloadTokens.
Dygerati

Ayrıca [KOVA] edilir bucket.name, bunu hardcode veya ekstra yerel var kullanmak gerekmez
Călin Darie

4
Bu çözümle ilgili sorun, hizmet URL'sinin kodlanmış olmasıdır. Firebase / Google bunu değiştirirse bozulabilir. Özelliğin kullanılması metadata.mediaLinkböyle bir sorunu önler.
Laurent

2
Bunun gibi bir URL oluşturmak desteklenmez. Bugün işe yarayabilir, ancak gelecekte bozulabilir. Uygun bir indirme URL'si oluşturmak için yalnızca sağlanan API'leri kullanmalısınız.
Doug Stevenson

1
Değişebilecek sabit kodlanmış bir URL'ye güvenmek kötü bir seçimdir.
Laurent

23

Bir Firebase projesi üzerinde çalışıyorsanız, diğer kitaplıkları eklemeden veya bir kimlik bilgileri dosyası indirmeden bir Cloud Function'ta imzalanmış URL'ler oluşturabilirsiniz. Yalnızca IAM API'yi etkinleştirmeniz ve mevcut hizmet hesabınıza bir rol eklemeniz gerekir (aşağıya bakın).

Yönetici kitaplığını başlatın ve normalde yaptığınız gibi bir dosya referansı alın:

import * as functions from 'firebase-functions'
import * as admin from 'firebase-admin'

admin.initializeApp(functions.config().firebase)

const myFile = admin.storage().bucket().file('path/to/my/file')

Daha sonra ile imzalanmış bir URL oluşturursunuz

myFile.getSignedUrl({action: 'read', expires: someDateObj}).then(urls => {
    const signedUrl = urls[0]
})

Firebase hizmet hesabınızın bunu çalıştırmak için yeterli izinlere sahip olduğundan emin olun

  1. Google API konsoluna gidin ve IAM API'yi etkinleştirin ( https://console.developers.google.com/apis/api/iam.googleapis.com/overview )
  2. Yine API konsolunda, ana menüye gidin, "IAM ve yönetici" -> "IAM"
  3. "App Engine varsayılan hizmet hesabı" rolü için düzenle'yi tıklayın
  4. "Başka bir rol ekle" yi tıklayın ve "Hizmet Hesabı Jetonu Oluşturucu" adlı rolü ekleyin
  5. Değişikliklerin yayılması için kaydedin ve bir dakika bekleyin

Vanilya Firebase yapılandırması ile, yukarıdaki kodu ilk kez çalıştırdığınızda, Kimlik ve Erişim Yönetimi (IAM) API'sinin daha önce XXXXXX projesinde kullanılmadığı veya devre dışı bırakıldığı bir hata alırsınız . . Hata mesajındaki bağlantıyı izler ve IAM API'yi etkinleştirirseniz, başka bir hata alırsınız: Bu işlemi my-service-account hizmet hesabında gerçekleştirmek için iam.serviceAccounts.signBlob izni gerekir . Token Oluşturucu rolünün eklenmesi, bu ikinci izin sorununu düzeltir.


Tam da nihayetinde zor yoldan anladığım aynı ayrıntılarla bir cevap bırakmak üzereydim - kesin çözümleri bu kadar önceden okumuş olsaydım: / 12/12/18 itibarıyla bu benim için çalıştı. Ayrıntılı talimatlar için teşekkürler, yeni başlayanlar için çok yararlı !!
Kat

2
İmzalı url'imin süresi 2 hafta içinde doluyor ancak admin.initializeApp () anahtarsız kullanıyorum, sorun bu mu? App Engine uygulamasının varsayılan hizmet hesabım "sahip" ve Cloud Functions Hizmet Aracısı olarak ayarlanmıştı, şimdilik "sahip" i kaldırdım ve "Service Account Token Creator" ı ekledim
Amit Bravo

2
İmzalanan URL'lerin süresi 7 gün içinde dolar. Daha kısa bir son kullanma tarihi ayarlayabilirsiniz ancak daha uzun olamaz.
Thomas David Kehoe

Süresi dolarsa url nasıl yenilenir?
Manoj MM

daha uzun süre ayarlamak için url nasıl yenilenir?
Saifallak

17

Başarılı bir şekilde kullandığım yöntemlerden biri, firebaseStorageDownloadTokensyükleme işlemini bitirdikten sonra dosyanın meta verilerinde adlandırılan bir anahtara UUID v4 değeri ayarlamak ve ardından indirme URL'sini Firebase'in bu URL'leri oluşturmak için kullandığı yapıyı izleyerek kendim bir araya getirmektir, örneğin:

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

Bu yöntemi kullanmanın ne kadar "güvenli" olduğunu bilmiyorum (Firebase'in gelecekte indirme URL'lerini oluşturma şeklini değiştirebileceği düşünüldüğünde), ancak uygulanması kolaydır.


1
Uuid değerini belirlediğiniz bir örnek var mı?
Drew Beaupre

1
Drew ile aynı soruyu soruyorum, meta verileri nerede ayarlıyorsunuz? Kova.upload işlevi çalışırken ayarlamaya çalıştım, çalışmadı.
Vysakh Sreenivasan

1
Vysakh, örnekle tam bir cevap gönderdim. Umarım bu size yardımcı olur.
Drew Beaupre

Jetonu nerede / nasıl oluşturursunuz?
CodyBugstein

3
İndirme URL'lerinin opak olması ve bileşenleri parçalanmaması veya birleştirilmemesi gerektiği için bu tekniği "güvenli" olarak kabul etmiyorum.
Doug Stevenson

16

Firebase Admin SDK serviceAccountKey.json dosyasının nereye gitmesi gerektiğini merak edenler için. Sadece işlevler klasörüne yerleştirin ve her zamanki gibi dağıtın.

Javascript SDK'da yaptığımız gibi indirme url'sini meta verilerden neden alamadığımız hala beni şaşırtıyor. Sonunda sona erecek bir url oluşturmak ve onu veritabanına kaydetmek arzu edilmez.


16

Kodunuzda URL ön ekini karıştırmaktan kaçınmalısınız . Cloud Storage NodeJS 1.6.x veya + predefinedAcl: 'publicRead'ile bir dosya yüklerken bu seçeneği kullanmanızı öneririm :

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

bucket.upload(attachment, options);

Ardından, genel URL'yi almak şu kadar basittir:

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);
});

2
Aslında işe yarıyor gibi görünüyor. Şimdiye kadar gördüğüm tek dezavantajı, bir tarayıcının URL çubuğundaki görüntüyü tıklarsanız, görüntüyü satır içinde görüntülemek yerine indireceği.
Michael Giovanni Pumo

file.getMetadata (), dosya referansında save () yöntemini kullandıktan sonra benim için hile yaptı. Firebase-admin sdk ile NodeJS'de kullanma.
Pascal Lamers

işe yaramadı, Anonim arayanın depolama alanına sahip olmadığını alıyorum. your_app / image.jpg
Manoj MM

9

Maalesef saygınlığım olmadığı için yukarıdaki sorunuza yorum gönderemiyorum, bu yüzden bu cevaba ekleyeceğim.

İmzalı bir URL oluşturarak yukarıda belirtildiği gibi yapın, ancak hizmet-account.json yerine, adresinde oluşturabileceğiniz serviceAccountKey.json'u kullanmanız gerektiğini düşünüyorum (buna göre YOURPROJECTID değiştirin)

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

Misal:

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 
        })

9

James Daniels'ın verdiği cevap hakkında yorum yapamam ama bence bu okumak çok önemli.

İmzalı bir URL vermek, birçok durumda oldukça kötü ve muhtemelen Tehlikeli görünüyor . Firebase belgelerine göre, imzalanan url'nin süresi bir süre sonra dolar, bu nedenle bunu veritabanınıza eklemek, belirli bir zaman diliminden sonra boş bir url'ye yol açar.

Oradaki Belgeler yanlış anlaşılmış olabilir ve imzalı url'nin süresi dolmaz, bu da sonuç olarak bazı güvenlik sorunlarına neden olabilir. Anahtar yüklenen her dosya için aynı görünüyor. Bu, bir dosyanın url'sini aldığınızda, birisinin erişmesi beklenmeyen dosyalara yalnızca adlarını bilerek kolayca erişebileceği anlamına gelir.

Bunu yanlış anladıysam, düzeltilmek için lvoe olurdum. Başka biri muhtemelen yukarıda belirtilen çözümü güncellemelidir. Orada yanılıyorsam


8

Şu anda kullandığım şey bu, basit ve kusursuz çalışıyor.

Google Cloud ile hiçbir şey yapmanıza gerek yok. Firebase ile kutudan çıktığı gibi çalışır ..

// Save the base64 to storage.
const file = admin.storage().bucket('url found on the storage part of firebase').file(`profile_photos/${uid}`);
await file.save(base64Image, {
    metadata: {
      contentType: 'image/jpeg',
    },
    predefinedAcl: 'publicRead'
});
const metaData = await file.getMetadata()
const url = metaData[0].mediaLink

DÜZENLEME: Aynı örnek, ancak yükleme ile:

await bucket.upload(fromFilePath, {destination: toFilePath});
file = bucket.file(toFilePath);
metaData = await file.getMetadata()
const trimUrl = metaData[0].mediaLink

#update: Meta verileri almak için yükleme yönteminde iki farklı çağrı yapmaya gerek yoktur:

let file = await bucket.upload(fromFilePath, {destination: toFilePath});
const trimUrl = file[0].metaData.mediaLink

1
Base64 ile kodlanmamış bir dosyayla onu nasıl kullanırsınız?
Tibor Udvari

1
MediaLinkenter değil, sadece mediaLink
l2aelba

1
MediaLink i.stack.imgur.com/B4Fw5.png bulamıyorum
sarah

@Sarah Bunu typcript kullanarak yazdım, modül değişimi olup olmadığından emin değilim.
Oliver Dixon

4

Önceden tanımlanmış erişim kontrol listeleri 'publicRead' değerini kullanırsanız, dosyayı yükleyebilir ve çok basit bir url yapısı ile ona erişebilirsiniz:

// Upload to GCS
const opts: UploadOptions = {
  gzip: true,
  destination: dest, // 'someFolder/image.jpg'
  predefinedAcl: 'publicRead',
  public: true
};
return bucket.upload(imagePath, opts);

Daha sonra url'yi şu şekilde oluşturabilirsiniz:

const storageRoot = 'https://storage.googleapis.com/';
const bucketName = 'myapp.appspot.com/'; // CHANGE TO YOUR BUCKET NAME
const downloadUrl = storageRoot + bucketName + encodeURIComponent(dest);

3

Aynı sorunu yaşadım, ancak README yerine firebase işlevi örneğinin koduna bakıyordum. Ve bu konudaki cevaplar da yardımcı olmadı ...

Aşağıdakileri yaparak yapılandırma dosyasını iletmekten kaçınabilirsiniz:

Projenizin Bulut Konsolu> IAM ve yönetici> IAM'ye gidin , App Engine varsayılan hizmet hesabını bulun ve bu üyeye Hizmet Hesabı Simgesi Oluşturucu rolünü ekleyin. Bu, uygulamanızın görüntülere imzalı genel URL'ler oluşturmasına olanak tanır.

kaynak: Otomatik Olarak Küçük Resim Oluşturma işlevi BENİOKU

Uygulama motoru rolünüz şöyle görünmelidir:

Bulut Konsolu


2

Bu, yalnızca basit bir URL'ye sahip genel bir dosyaya ihtiyacınız varsa çalışır. Bunun Firebase depolama kurallarınızı geçersiz kılabileceğini unutmayın.

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

Firebase SDK kullananlar veadmin.initializeApp :

1 - Bir Özel Anahtar oluşturun ve / functions klasörüne yerleştirin.

2 - Kodunuzu aşağıdaki gibi yapılandırın:

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

belgeleme

Try / catch, diğer dosyaları içe aktaran ve her dosyaya bir işlev oluşturan bir index.js kullanmamdan kaynaklanıyor. Tüm işlevlere sahip tek bir index.js dosyası kullanıyorsanız, sorun yok admin.initializeApp(Object.assign(functions.config().firebase, { credential: admin.credential.cert(serviceAccount) }));.


benim için "../serviceaccountkey.json" idi, ancak ../
robert king

1

Firebase 6.0.0'dan itibaren, depolama alanına doğrudan yönetici ile şu şekilde erişebildim:

const bucket = admin.storage().bucket();

Bu yüzden bir hizmet hesabı eklememe gerek kalmadı. Ardından UUID'yi yukarıda belirtildiği gibi ayarlamak firebase url'sini almak için çalıştı.


1

Bu bulduğum en iyisi. Gereksiz ama benim için işe yarayan tek makul çözüm.

await bucket.upload(localFilePath, {destination: uploadPath, public: true});
const f = await bucket.file(uploadPath)
const meta = await f.getMetadata()
console.log(meta[0].mediaLink)

1

olmadan signedURL()kullanarakmakePublic()

const functions = require('firebase-functions');
const admin = require('firebase-admin');

admin.initializeApp()
var bucket = admin.storage().bucket();

// --- [Above] for admin related operations, [Below] for making a public url from a GCS uploaded object

const { Storage } = require('@google-cloud/storage');
const storage = new Storage();

exports.testDlUrl = functions.storage.object().onFinalize(async (objMetadata) => {
    console.log('bucket, file', objMetadata.bucket + ' ' + objMetadata.name.split('/').pop()); // assuming file is in folder
    return storage.bucket(objMetadata.bucket).file(objMetadata.name).makePublic().then(function (data) {
        return admin.firestore().collection('publicUrl').doc().set({ publicUrl: 'https://storage.googleapis.com/' + objMetadata.bucket + '/' + objMetadata.name }).then(writeResult => {
            return console.log('publicUrl', writeResult);
        });
    });
});


0

Hata alıyorsanız:

Google Cloud İşlevleri: required (…) bir işlev değildir

bunu dene:

const {Storage} = require('@google-cloud/storage');
const storage = new Storage({keyFilename: 'service-account-key.json'});
const bucket = storage.bucket(object.bucket);
const file = bucket.file(filePath);
.....

0

Zaten yanıtlarımı aşağıdaki URL'ye gönderiyorum Çözüm ile tam kodu nereden edinebilirsiniz

Base64 olarak kodlanmış bir görüntüyü (dize) Node.js kullanarak doğrudan bir Google Cloud Storage paketine nasıl yüklerim?

const uuidv4 = require('uuid/v4');
const uuid = uuidv4();

    const os = require('os')
    const path = require('path')
    const cors = require('cors')({ origin: true })
    const Busboy = require('busboy')
    const fs = require('fs')
    var admin = require("firebase-admin");


    var serviceAccount = {
        "type": "service_account",
        "project_id": "xxxxxx",
        "private_key_id": "xxxxxx",
        "private_key": "-----BEGIN PRIVATE KEY-----\jr5x+4AvctKLonBafg\nElTg3Cj7pAEbUfIO9I44zZ8=\n-----END PRIVATE KEY-----\n",
        "client_email": "xxxx@xxxx.iam.gserviceaccount.com",
        "client_id": "xxxxxxxx",
        "auth_uri": "https://accounts.google.com/o/oauth2/auth",
        "token_uri": "https://oauth2.googleapis.com/token",
        "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
        "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/firebase-adminsdk-5rmdm%40xxxxx.iam.gserviceaccount.com"
      }

    admin.initializeApp({
        credential: admin.credential.cert(serviceAccount),
        storageBucket: "xxxxx-xxxx" // use your storage bucket name
    });


    const app = express();
    app.use(bodyParser.urlencoded({ extended: false }));
    app.use(bodyParser.json());
app.post('/uploadFile', (req, response) => {
    response.set('Access-Control-Allow-Origin', '*');
    const busboy = new Busboy({ headers: req.headers })
    let uploadData = null
    busboy.on('file', (fieldname, file, filename, encoding, mimetype) => {
        const filepath = path.join(os.tmpdir(), filename)
        uploadData = { file: filepath, type: mimetype }
        console.log("-------------->>",filepath)
        file.pipe(fs.createWriteStream(filepath))
      })

      busboy.on('finish', () => {
        const bucket = admin.storage().bucket();
        bucket.upload(uploadData.file, {
            uploadType: 'media',
            metadata: {
              metadata: { firebaseStorageDownloadTokens: uuid,
                contentType: uploadData.type,
              },
            },
          })

          .catch(err => {
            res.status(500).json({
              error: err,
            })
          })
      })
      busboy.end(req.rawBody)
   });




exports.widgets = functions.https.onRequest(app);
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.