फायरबेस के लिए क्लाउड फ़ंक्शंस के साथ अपलोड की गई फ़ाइल से डाउनलोड URL प्राप्त करें


125

फायरबेस के लिए फ़ंक्शंस के साथ फायरबेस स्टोरेज में एक फ़ाइल अपलोड करने के बाद, मैं फ़ाइल का डाउनलोड यूआरएल प्राप्त करना चाहता हूं।

मेरे पास यह है :

...

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

        // Get the download url of file

    });

ऑब्जेक्ट फ़ाइल में बहुत सारे पैरामीटर हैं। यहां तक ​​कि एक का नाम भीmediaLink । हालाँकि, यदि मैं इस लिंक तक पहुँचने का प्रयास करता हूँ, तो मुझे यह त्रुटि मिलती है:

अनाम उपयोगकर्ताओं के पास संग्रहण.objects.get का उपयोग ऑब्जेक्ट तक नहीं है ...

क्या कोई मुझे बता सकता है कि जनता को यूआरएल कैसे डाउनलोड करना है?

धन्यवाद


इस पोस्ट को भी देखें जो फ़ंक्शन में उपलब्ध डेटा से URL को फिर से संगठित करता है।
काटो

जवाबों:


134

आपको @ google-cloud / storage NPM मॉड्यूल के माध्यम से getSignurL का उपयोग करके एक हस्ताक्षरित URL जनरेट करना होगा ।

उदाहरण:

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

आपको अपने सेवा खाते के क्रेडेंशियल्स के@google-cloud/storage साथ आरंभ करने की आवश्यकता होगी क्योंकि एप्लिकेशन डिफ़ॉल्ट क्रेडेंशियल पर्याप्त नहीं होंगे।

UPDATE : क्लाउड स्टोरेज SDK को अब Firebase Admin SDK के जरिए एक्सेस किया जा सकता है, जो @ google-cloud / स्टोरेज के आसपास एक रैपर की तरह काम करता है । एक ही तरीका है अगर आप या तो:

  1. एसडीके एक विशेष सेवा खाते के साथ, आमतौर पर एक दूसरे, गैर-डिफ़ॉल्ट उदाहरण के माध्यम से।
  2. या, एक सेवा खाते के बिना, डिफ़ॉल्ट ऐप इंजन सेवा खाते को "साइनब्लोब" अनुमति देकर।

75
यह अजीब है। फ़ायरबॉइड एंड्रॉइड, आईओएस और वेब एसडीके का उपयोग करते समय हम स्टोरेज संदर्भ से डाउनलोड यूआरएल आसानी से प्राप्त कर सकते हैं। व्यवस्थापन में रहते हुए यह इतना आसान क्यों नहीं है? पुनश्च: जहाँ मैं 'सर्विस-अकाउंट.जॉन' को gcs को इनिशियलाइज़ करने के लिए आवश्यक पा सकता हूँ?
वैलेंटाइन

2
इसका कारण यह है कि व्यवस्थापक-एसडीके में कोई क्लाउड स्टोरेज अतिरिक्त नहीं है। आप अपना व्यवस्थापक-sdk सेवा खाता json यहाँ कंसोल
जेम्स डेनियल

18
इस पद्धति से उत्पन्न URL हास्यास्पद रूप से लंबा है। @Martemorfosis प्रस्तावित विधि द्वारा उत्पन्न URL ज्यादा बेहतर है। क्या कोई ऐसा फ़ंक्शन है जो उस URL का उत्पादन करता है? जब मैं फायरबेस-एसडीके का उपयोग कर रहा हूं तो मैं भविष्य में उपयोग के लिए डेटाबेस में बचत करता हूं। एक दर्पण विधि को कार्य डोमेन में मौजूद होना चाहिए।
बोगैक

3
हम तैनात फ़ंक्शंस के साथ सेवा-खाता.जॉन को कैसे अपलोड कर सकते हैं? मैंने इसे फ़ंक्शंस फ़ोल्डर में रखने और पैकेज फ़ील्ड में फ़ाइल फ़ील्ड में संदर्भित करने का प्रयास किया है। लेकिन इसे तैनात नहीं किया जा रहा है। धन्यवाद।
डेविड आरोस्ती

2
क्या हमें जोड़ना होगा actionऔर expires?
चाड बिंघम

83

अपलोड पर डाउनलोड टोकन निर्दिष्ट करने के तरीके के बारे में एक उदाहरण यहां दिया गया है:

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

इसके बाद कॉल करें

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

यहां महत्वपूर्ण बात यह है कि विकल्प संपत्ति के metadataभीतर निहित एक वस्तु metadataहै। firebaseStorageDownloadTokensएक uuid-v4 मान पर सेट करना क्लाउड स्टोरेज को यह बताने के लिए उपयोग करेगा कि इसका सार्वजनिक स्रोत टोकन है।

@Martemorfosis के लिए बहुत धन्यवाद


संग्रहण पर पहले से अपलोड की गई फ़ाइल के लिए मुझे वैध UUID टोकन कैसे मिलेगा? यादृच्छिक UUID उत्पन्न करने से मदद नहीं मिली। कोई संकेत?
डेरफैजियो

3
@Martemorfosis पोस्ट में जवाब मिला। UUID को object.metadata export.uploadProfilePic = functions.storage.object ()। OnChange (इवेंट => {const ऑब्जेक्ट = event.data; // स्टोरेज ऑब्जेक्ट; const tuid = object.metadata.firebaseStorageDownloadTokens) से प्राप्त किया जा सकता है। // ...
डेरफैजियो

बाल्टी उदाहरण के लिए धन्यवाद! मैं लगभग 1 घंटे के लिए बाल्टी और फ़ाइल विधियों के लिए विभिन्न संयोजनों की कोशिश कर रहा था :)
JCarlosR

1
आपके उत्तर के लिए धन्यवाद! मेरे मामले में, मैं bucket.file (fileName) .createWriteStream के साथ अपलोड कर रहा था, जो अपलोड पूरा होने पर डेटा वापस नहीं करता है, परिणामस्वरूप, मैंने encodeURIComponent (file.name) के बजाय encodeURIComponent (fileName) का उपयोग किया।
स्टेनिस्लॉ बुज़ुनको

2
यह सही उत्तर होना चाहिए। यह फायरबेस एसडीके (@DevMike) द्वारा उत्पन्न एक के समान URL में परिणत होता है, और मैं इसके ठीक पीछे शर्त लगाता हूं कि वे पर्दे के पीछे क्या करते हैं।
शमूएल ई।

65

यह उत्तर Google / Firebase Cloud Storage में फ़ाइल अपलोड करते समय डाउनलोड URL प्राप्त करने के विकल्पों को संक्षेप में प्रस्तुत करेगा। डाउनलोड यूआरएल तीन प्रकार के होते हैं:

  1. डाउनलोड किए गए डाउनलोड किए गए URL, जो अस्थायी हैं और जिनमें सुरक्षा सुविधाएँ हैं
  2. टोकन डाउनलोड URL, जो लगातार बने रहते हैं और उनमें सुरक्षा विशेषताएं होती हैं
  3. सार्वजनिक डाउनलोड URL, जो लगातार हैं और सुरक्षा की कमी है

टोकन डाउनलोड URL प्राप्त करने के तीन तरीके हैं। अन्य दो डाउनलोड URL के पास उन्हें प्राप्त करने का केवल एक ही तरीका है।

फायरबेस स्टोरेज कंसोल से

आप फायरबेस स्टोरेज कंसोल से डाउनलोड URL प्राप्त कर सकते हैं:

यहां छवि विवरण दर्ज करें

डाउनलोड URL इस तरह दिखता है:

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

पहला भाग आपकी फ़ाइल का एक मानक पथ है। अंत में एक टोकन है। यह डाउनलोड URL स्थायी है, अर्थात, यह समाप्त नहीं होगा, हालाँकि आप इसे रद्द कर सकते हैं।

getDownloadURL () फ्रंट एंड से

प्रलेखन उपयोग करने के लिए हमें बताता है getDownloadURL():

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

यह वही डाउनलोड URL प्राप्त करता है जिसे आप अपने Firebase Storage कंसोल से प्राप्त कर सकते हैं। यह विधि आसान है लेकिन इसके लिए आवश्यक है कि आप अपनी फ़ाइल का पथ जानें, जो कि मेरे ऐप में अपेक्षाकृत सरल डेटाबेस संरचना के लिए कोड की लगभग 300 लाइनें हैं। यदि आपका डेटाबेस जटिल है तो यह एक बुरा सपना होगा। और आप सामने के छोर से फ़ाइलें अपलोड कर सकते हैं, लेकिन यह आपके क्रेडेंशियल्स को आपके ऐप को डाउनलोड करने वाले किसी भी व्यक्ति को उजागर करेगा। इसलिए अधिकांश परियोजनाओं के लिए आप अपनी फ़ाइलों को अपने नोड बैक एंड या Google क्लाउड फ़ंक्शंस से अपलोड करना चाहते हैं, फिर डाउनलोड URL प्राप्त करें और इसे अपनी फ़ाइल के बारे में अन्य डेटा के साथ अपने डेटाबेस में सहेजें।

अस्थायी डाउनलोड URL के लिए getSignUrl ()

getSignedUrl () एक नोड बैक एंड या Google क्लाउड फ़ंक्शंस से उपयोग करना आसान है:

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

एक हस्ताक्षरित डाउनलोड URL इस तरह दिखता है:

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

हस्ताक्षर किए गए URL की समाप्ति तिथि और लंबे हस्ताक्षर हैं। कमांड लाइन gsutil signurl -d के लिए प्रलेखन कहता है कि हस्ताक्षर किए गए URL अस्थायी हैं: डिफ़ॉल्ट समाप्ति एक घंटा है और अधिकतम समाप्ति सात दिन है।

मैं यहाँ शेख़ी करने जा रहा हूँ कि getSignedUrl कभी नहीं कहता है कि आपका हस्ताक्षरित URL एक सप्ताह में समाप्त हो जाएगा। दस्तावेज़ीकरण कोड 3-17-2025की समाप्ति तिथि है, यह सुझाव देते हुए कि आप भविष्य में समाप्ति वर्ष निर्धारित कर सकते हैं। मेरे ऐप ने पूरी तरह से काम किया, और फिर एक हफ्ते बाद दुर्घटनाग्रस्त हो गया। त्रुटि संदेश में कहा गया है कि हस्ताक्षर मेल नहीं खाते, ऐसा नहीं है कि डाउनलोड URL की समय सीमा समाप्त हो गई थी। मैंने अपने कोड में कई बदलाव किए, और सब कुछ काम किया ... जब तक कि यह सब एक हफ्ते बाद दुर्घटनाग्रस्त नहीं हो गया। यह एक महीने से अधिक की निराशा के लिए चला गया।

अपनी फ़ाइल सार्वजनिक रूप से उपलब्ध कराएँ

आप अपनी फ़ाइल पर अनुमतियों को सार्वजनिक रूप से पढ़ने के लिए सेट कर सकते हैं, जैसा कि प्रलेखन में समझाया गया है । यह क्लाउड स्टोरेज ब्राउज़र या आपके नोड सर्वर से किया जा सकता है। आप एक फ़ाइल को सार्वजनिक कर सकते हैं या एक निर्देशिका या आपके संपूर्ण संग्रहण डेटाबेस को बना सकते हैं। यहाँ नोड कोड है:

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

परिणाम आपके क्लाउड स्टोरेज ब्राउज़र में इस तरह दिखेगा:

यहां छवि विवरण दर्ज करें

कोई भी आपकी फ़ाइल को डाउनलोड करने के लिए मानक पथ का उपयोग कर सकता है:

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

किसी फ़ाइल को सार्वजनिक करने का एक और तरीका है मेक रिपब्लिक () का उपयोग करना । मैं यह काम करने में सक्षम नहीं हूं, यह बाल्टी पाने के लिए मुश्किल है और रास्ते सही हैं।

एक दिलचस्प विकल्प एक्सेस कंट्रोल लिस्ट का उपयोग करना है । आप केवल उन्हीं उपयोगकर्ताओं को फाइल उपलब्ध करवा सकते हैं जिन्हें आप सूची में रखते हैं, या authenticatedReadGoogle खाते से लॉग-इन करने के लिए फाइल उपलब्ध कराने के लिए उपयोग करते हैं। अगर कोई विकल्प होता "कोई भी जो Firebase Auth का उपयोग करके मेरे ऐप में लॉग इन करता" तो मैं इसका उपयोग करता, क्योंकि यह केवल मेरे उपयोगकर्ताओं तक पहुंच को सीमित करता था।

FirebaseStorageDownloadTokens के साथ अपना खुद का डाउनलोड URL बनाएँ

कई उत्तर एक अनिर्दिष्ट Google संग्रहण ऑब्जेक्ट संपत्ति का वर्णन करते हैं firebaseStorageDownloadTokens। इससे आप स्टोरेज टोकन को बता सकते हैं जिसका आप उपयोग करना चाहते हैं। आप uuidनोड मॉड्यूल के साथ एक टोकन उत्पन्न कर सकते हैं । कोड की चार लाइनें और आप अपना स्वयं का डाउनलोड URL बना सकते हैं, वही डाउनलोड URL जो आपको कंसोल से मिलता है या getDownloadURL()। कोड की चार लाइनें हैं:

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

यहाँ संदर्भ में कोड है:

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

यह एक टाइपो नहीं है - आपको घोंसला बनाना होगा firebaseStorageDownloadTokens दोहरी परतों मेंmetadata: !

डग स्टीवेन्सन ने बताया कि firebaseStorageDownloadTokensयह आधिकारिक Google क्लाउड स्टोरेज सुविधा नहीं है। आप इसे किसी भी Google दस्तावेज़ में नहीं पाएंगे, और इसका कोई वादा नहीं है कि यह भविष्य के संस्करण में होगा@google-cloud । मुझे पसंद है firebaseStorageDownloadTokensक्योंकि यह वही है जो मैं चाहता हूं, लेकिन यह एक "गंध" है जिसका उपयोग करना सुरक्षित नहीं है।

क्यों नहीं GetDownloadURL () नोड से?

जैसा कि @ क्लिंटन ने लिखा, Google को (यानी, आपका नोड बैक एंड) file.getDownloadURL()में एक तरीका बनाना चाहिए @google-cloud/storage। मैं Google क्लाउड फ़ंक्शंस से एक फ़ाइल अपलोड करना चाहता हूं और टोकन डाउनलोड URL प्राप्त करना चाहता हूं।


11
मैंने इसके लिए एक मुद्दा बनाया @google-cloud/storage, इसे +1 करने के लिए स्वतंत्र महसूस करें;) github.com/googleapis/nodejs-storage/issues/697
Théo Champion

1
नवीनतम मेक रिपब्लिक () लिंक।
गलकी

1
लगता है firebaseStorageDownloadTokensअब काम नहीं करता।
मेसन

1
स्वीकृत उत्तर बताता है कि लगातार डाउनलोड यूआरएल प्राप्त करना संभव नहीं है जो समाप्त नहीं होता है जो सही नहीं है। आपके उत्तर में यहाँ का विवरण उत्कृष्ट है और इसे सही उत्तर के रूप में चिह्नित किया जाना चाहिए। धन्यवाद।
देवमीक

2
@ कमाल सारांश के लिए धन्यवाद! आपने उल्लेख किया है कि लगातार डाउनलोड URL प्राप्त करने के लिए 3 तरीके हैं, लेकिन आपने केवल 2 साझा किया: (ए) फायरबेस स्टोरेज कंसोल से, और (बी) गेटडाउनलोड () फ्रंट एंड से। मुझे आश्चर्य है कि तीसरा तरीका क्या है?
czphilip

23

फ़ंक्शंस ऑब्जेक्ट रिस्पॉन्स में हाल के बदलावों के साथ आप सब कुछ प्राप्त कर सकते हैं जो आपको एक साथ डाउनलोड यूआरएल जैसे "सिलाई" करने की ज़रूरत है:

 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
क्या आप ऑब्जेक्ट रिस्पॉन्स से रेफर कर रहे हैं bucket.file().upload()? मुझे प्रतिक्रिया डेटा में कोई मेटाडेटा संपत्ति नहीं मिली है, और मुझे यकीन नहीं है कि ये कैसे प्राप्त करें firebaseStorageDownloadTokens
दियाराती

[आपका BUCKET] भी है bucket.name, आपको इसे हार्डकोड करने या अतिरिक्त स्थानीय
संस्करण का

4
इस समाधान के साथ समस्या यह है कि सेवा URL हार्डकोड है। अगर Firebase / Google इसे बदलते हैं, तो यह टूट सकता है। metadata.mediaLinkसंपत्ति का उपयोग इस तरह के मुद्दे को रोकता है।
लॉरेंट

2
इस तरह का URL बनाने के लिए यह समर्थित मामला नहीं है। यह आज काम कर सकता है, लेकिन भविष्य में टूट सकता है। एक उचित डाउनलोड URL उत्पन्न करने के लिए आपको केवल दिए गए API का उपयोग करना चाहिए।
डग स्टीवेन्सन

1
एक हार्डकॉक्ड URL पर भरोसा करना जो बदल सकता है एक बुरा विकल्प है।
लॉरेंट

23

यदि आप फायरबेस परियोजना पर काम कर रहे हैं, तो आप अन्य पुस्तकालयों को शामिल किए बिना या क्रेडेंशियल फ़ाइल डाउनलोड किए बिना क्लाउड फ़ंक्शन में हस्ताक्षरित URL बना सकते हैं। आपको बस IAM API को सक्षम करने और अपने मौजूदा सेवा खाते में एक भूमिका जोड़ने की आवश्यकता है (नीचे देखें)।

व्यवस्थापक लाइब्रेरी को आरम्भ करें और सामान्य रूप से फ़ाइल संदर्भ प्राप्त करें:

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

आप तब एक हस्ताक्षरित URL जनरेट करते हैं

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

सुनिश्चित करें कि आपके Firebase सेवा खाते को इसे चलाने के लिए पर्याप्त अनुमति है

  1. Google API कंसोल पर जाएं और IAM API ( https://console.developers.google.com/apis/api/iam.googleapis.com/overview ) सक्षम करें
  2. अभी भी एपीआई कंसोल में, मुख्य मेनू पर जाएं, "IAM & admin" -> "IAM"
  3. "ऐप इंजन डिफ़ॉल्ट सेवा खाता" भूमिका के लिए संपादन पर क्लिक करें
  4. "एक और भूमिका जोड़ें" पर क्लिक करें, और "सेवा खाता टोकन निर्माता" नामक एक जोड़ें
  5. परिवर्तनों को प्रचारित करने के लिए एक मिनट बचाएं और प्रतीक्षा करें

वेनिला फायरबेस कॉन्फिग के साथ, पहली बार जब आप उपरोक्त कोड चलाते हैं तो आपको एक त्रुटि पहचान और एक्सेस मैनेजमेंट (IAM) एपीआई मिलेगा जिसका उपयोग XXXXXX से पहले प्रोजेक्ट में नहीं किया गया है या यह अक्षम है। । यदि आप त्रुटि संदेश में लिंक का अनुसरण करते हैं और IAM API को सक्षम करते हैं, तो आपको एक और त्रुटि मिलेगी : अनुमति iam.serviceAccounts.signBlob को यह ऑपरेशन सेवा खाता my-service-account पर करने की आवश्यकता है । टोकन क्रिएटर भूमिका जोड़ना इस दूसरी अनुमति समस्या को ठीक करता है।


मैं मूल रूप से इन्हीं विवरणों के साथ एक उत्तर छोड़ने वाला था, जिन्हें मैंने अंतिम रूप से कठिन तरीके से खोजा था - निश्चित रूप से इच्छा कि मैंने पहले इस समाधान को नीचे तक पढ़ा था: / इसने मेरे लिए 12/12/18 तक काम किया। विस्तृत निर्देशों के लिए धन्यवाद, हमारे लिए बहुत उपयोगी है !!
कैट

2
मेरा हस्ताक्षर 2 सप्ताह में समाप्त हो रहा है, लेकिन मैं बिना किसी कुंजी के admin.initializeApp () का उपयोग कर रहा हूं, क्या यह समस्या है? मेरे पास "स्वामी" और क्लाउड फ़ंक्शंस सर्विस एजेंट के लिए ऐप इंजन ऐप डिफ़ॉल्ट सेवा खाता सेट था, मैंने अभी के लिए "स्वामी" को हटा दिया और "सेवा खाता टोकन क्रिएटर" जोड़ दिया
अमित ब्रावो

2
7 दिनों में हस्ताक्षरित URL समाप्त हो जाते हैं। आप एक छोटी समाप्ति तिथि निर्धारित कर सकते हैं लेकिन अधिक समय तक नहीं।
थॉमस डेविड केहो

यदि यह समाप्त हो जाता है तो url को ताज़ा कैसे करें?
मनोज एमएम

अधिक समय तक इसे सेट करने के लिए url को ताज़ा कैसे करें?
सैफल्लाक

17

एक विधि जो मैं सफलता के साथ उपयोग कर रहा हूं, वह है यूयूआईडी v4 मान को firebaseStorageDownloadTokensफ़ाइल के मेटाडेटा में एक कुंजी के नाम पर सेट करने के बाद इसे अपलोड करना समाप्त करना और फिर डाउनलोड यूआरएल को स्वयं इकट्ठा करना, संरचना के बाद फायरबेस इन यूआरएल को उत्पन्न करने के लिए उपयोग करता है, जैसे:

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

मुझे नहीं पता कि इस पद्धति का उपयोग करना कितना "सुरक्षित" है (यह देखते हुए कि फायरबेस बदल सकता है कि यह भविष्य में डाउनलोड URL कैसे उत्पन्न करता है) लेकिन इसे लागू करना आसान है।


1
क्या आपके पास एक उदाहरण है जहां आपने uuid मान सेट किया है?
ड्र्यू ब्यूप्रे

1
मेरे पास ड्रू के रूप में एक ही सवाल है, आप मेटाडेटा कहां सेट करते हैं? मैंने बकेट.अपलोड फंक्शन करते समय सेट करने की कोशिश की, काम नहीं किया।
वैसाख श्रीनिवासन

1
वैसाख, मैंने एक पूर्ण उत्तर w / उदाहरण पोस्ट किया है। आशा है कि आपकी मदद करता है
ड्रयू ब्यूप्रे

आप टोकन कहां / कैसे बनाते हैं?
कोडीबस्टीन

3
मैं इस तकनीक को "सुरक्षित" नहीं मानूंगा, क्योंकि डाउनलोड यूआरएल को अपारदर्शी माना जाता है, जिनके घटकों को नहीं तोड़ा या इकट्ठा किया जाना चाहिए।
डग स्टीवेन्सन

16

उन लोगों के लिए जहां फायरबेस व्यवस्थापक एसडीके सेवाअकाउंटके.जोन फ़ाइल को जाना चाहिए। बस इसे फ़ंक्शन फ़ोल्डर में रखें और हमेशा की तरह तैनात करें।

यह अभी भी मुझे चकित करता है कि हम मेटाडेटा से डाउनलोड यूआरएल क्यों नहीं प्राप्त कर सकते हैं जैसे हम जावास्क्रिप्ट एसडीके में करते हैं। एक यूआरएल उत्पन्न करना जो अंततः समाप्त हो जाएगा और इसे डेटाबेस में सहेजना वांछनीय नहीं है।


15

मेरा सुझाव है कि क्लाउड स्टोरेज NodeJS 1.6.x या + के predefinedAcl: 'publicRead'साथ फ़ाइल अपलोड करते समय विकल्प का उपयोग करें :

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

bucket.upload(attachment, options);

फिर, सार्वजनिक URL प्राप्त करना उतना ही सरल है:

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
यह वास्तव में काम करने के लिए प्रकट होता है। हालांकि मैं अभी तक केवल नकारात्मक पक्ष यह देखता हूं कि यदि आप किसी ब्राउज़र के URL बार में छवि को हिट करते हैं, तो यह इनलाइन देखने के बजाय छवि को डाउनलोड करेगा।
माइकल जियोवानी पुमो

file.getMetadata () ने फ़ाइल संदर्भ पर सेव () विधि का उपयोग करने के बाद मेरे लिए चाल चली। फायरबेस-एडमिन sdk के साथ NodeJS में इसका उपयोग करना।
पास्कल लैमर

काम नहीं कर रहा है, मुझे बेनामी कॉलर नहीं मिल रहा है। आपके पास__ / छवि पर पहुंच का भंडारण नहीं है। इमेज
मनोज एम.एम.

9

क्षमा करें, लेकिन मैं लापता प्रतिष्ठा के कारण आपके प्रश्न के ऊपर एक टिप्पणी पोस्ट नहीं कर सकता, इसलिए मैं इसे इस उत्तर में शामिल करूंगा।

जैसा कि एक हस्ताक्षरित यूआरएल उत्पन्न करके ऊपर कहा गया है, लेकिन इसके बजाय सेवा-खाता.जॉन का उपयोग करने के लिए मुझे लगता है कि आपको सेवा का उपयोग करना होगा।

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

उदाहरण:

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

जेम्स डेनियल ने जो जवाब दिया, उस पर मैं कोई टिप्पणी नहीं कर सकता, लेकिन मुझे लगता है कि यह पढ़ना बहुत जरूरी है।

एक हस्ताक्षर किए गए URL को बाहर देना जैसे उसने किया कई मामलों के लिए बहुत बुरा और संभव खतरनाक है । फायरबेस के दस्तावेज के अनुसार हस्ताक्षरित url कुछ समय के बाद समाप्त हो जाता है, इसलिए आपके डेटाबेस में जोड़ने से एक निश्चित समय सीमा के बाद एक खाली url हो जाएगा

यह हो सकता है कि वहां डॉक्यूमेंटेशन को गलत समझा जाए और हस्ताक्षरित url की समय सीमा समाप्त न हो, जिसके परिणामस्वरूप कुछ सुरक्षा समस्याएं होंगी। प्रत्येक अपलोड की गई फ़ाइल के लिए कुंजी समान लगती है। इसका मतलब है कि एक बार जब आप एक फ़ाइल का url प्राप्त कर लेते हैं, तो कोई भी आसानी से उन फ़ाइलों तक पहुंच सकता है, जिन्हें वे एक्सेस करने के लिए नहीं बताए गए हैं, बस उनका नाम जानकर।

अगर मैं गलत समझ गया तो मैं सुधारने के लिए कहूंगा। किसी को संभवतः उपरोक्त नामित समाधान का अद्यतन करना चाहिए। अगर मैं वहां गलत हो सकता हूं


7

यह वही है जो मैं वर्तमान में उपयोग करता हूं, यह सरल है और यह निर्दोष रूप से काम करता है।

आपको Google क्लाउड के साथ कुछ भी करने की आवश्यकता नहीं है। यह बॉक्स के बाहर काम करता है Firebase के साथ ..

// 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

संपादित करें: एक ही उदाहरण, लेकिन अपलोड के साथ:

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

अपडेट करें:

मेटाडेटा प्राप्त करने के लिए अपलोड विधि में दो अलग-अलग कॉल करने की आवश्यकता नहीं है:

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

1
आप इसे किसी ऐसी फ़ाइल के साथ कैसे उपयोग करेंगे जो कि बेस 64 एनकोडेड नहीं है?
टिबोर उदवरी

1
यह मीडियालिंक नहीं है, इसका सिर्फ मीडियालिंक है
l2aelba

1
मुझे मीडियालिंक नहीं मिल रहा है i.stack.imgur.com/B4Fw5.png
सारा

@ सरहा मैंने इसे टाइपस्क्रिप्ट का उपयोग करके लिखा है, यह सुनिश्चित नहीं है कि कुछ मॉड्यूल प्रतिस्थापन है।
ओलिवर डिक्सन

3

मेरे पास एक ही मुद्दा था, हालांकि, मैं आरईएडीएमई के बजाय फायरबेस फ़ंक्शन उदाहरण के कोड को देख रहा था। और इस धागे पर जवाब या तो मदद नहीं की ...

आप निम्न कार्य करके विन्यास फाइल को पास करने से बच सकते हैं:

अपनी परियोजना के क्लाउड कंसोल> IAM और व्यवस्थापक> IAM पर जाएं , एप्लिकेशन इंजन डिफ़ॉल्ट सेवा खाता ढूंढें और उस सदस्य के लिए सेवा खाता टोकन निर्माता भूमिका जोड़ें। यह आपके एप्लिकेशन को छवियों पर हस्ताक्षर किए गए सार्वजनिक URL बनाने की अनुमति देगा।

स्रोत: स्वचालित रूप से थंबनेल जनरेट करें README

ऐप इंजन के लिए आपकी भूमिका इस तरह दिखनी चाहिए:

क्लाउड कंसोल


3

यदि आप 'publicRead' के पूर्वनिर्धारित अभिगम नियंत्रण सूची मूल्य का उपयोग करते हैं, तो आप फ़ाइल को अपलोड कर सकते हैं और इसे बहुत ही सरल यूरेनियम संरचना के साथ एक्सेस कर सकते हैं:

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

फिर आप url का निर्माण इस तरह कर सकते हैं:

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

2

यह काम करता है अगर आपको एक साधारण यूआरएल के साथ एक सार्वजनिक फाइल की जरूरत है। ध्यान दें कि इससे आपके Firebase संग्रहण नियम समाप्त हो सकते हैं।

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 और का उपयोग कर रहे हैं admin.initializeApp:

1 - एक निजी कुंजी और जगह / कार्य फ़ोल्डर उत्पन्न करें

2 - अपने कोड को निम्नानुसार कॉन्फ़िगर करें:

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

प्रलेखन

कोशिश / पकड़ है क्योंकि मैं एक index.js का उपयोग कर रहा हूं जो अन्य फ़ाइलों को आयात करता है और प्रत्येक फ़ाइल के लिए एक फ़ंक्शन बनाता है। यदि आप सभी कार्यों के साथ एक एकल index.js फ़ाइल का उपयोग कर रहे हैं, तो आपको ठीक होना चाहिए admin.initializeApp(Object.assign(functions.config().firebase, { credential: admin.credential.cert(serviceAccount) }));


मेरे लिए यह '../serviceaccountkey.json' था, लेकिन सिर के लिए धन्यवाद .. का उपयोग करने के लिए ..
robert

1

Firebase 6.0.0 के रूप में मैं इस तरह सीधे व्यवस्थापक के साथ भंडारण का उपयोग करने में सक्षम था:

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

इसलिए मुझे सेवा खाता जोड़ने की आवश्यकता नहीं थी। फिर UUID की स्थापना ऊपर संदर्भित के रूप में फायरबेस url प्राप्त करने के लिए काम की।


1

यह सबसे अच्छा मैं आया हूं। यह बेमानी है, लेकिन एकमात्र उचित समाधान जो मेरे लिए काम करता है।

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

बिना signedURL()उपयोग केmakePublic()

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

यदि आपको त्रुटि हो रही है:

Google क्लाउड फ़ंक्शंस: की आवश्यकता है (…) एक फ़ंक्शन नहीं है

इसे इस्तेमाल करे:

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

मैं अपना ans पहले ही पोस्ट कर देता हूं ... नीचे URL में जहां आप समाधान के साथ पूर्ण कोड प्राप्त कर सकते हैं

मैं Node.js का उपयोग करके सीधे Google क्लाउड स्टोरेज बाल्टी में बेस 64 एनकोडेड इमेज (स्ट्रिंग) कैसे अपलोड करूं?

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);
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.