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




firebase firebase-storage (12)

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

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

...

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

        // Get the download url of file

    });

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

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

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

धन्यवाद


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

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

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


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

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 को बहुत धन्यवाद


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

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


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

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

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


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

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

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

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


जो लोग 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) {}

Documentation

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


मेरा सुझाव है कि क्लाउड स्टोरेज NodeJS 1.6.x / + के साथ एक फ़ाइल अपलोड करते समय, predefinedAcl: 'publicRead' विकल्प 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);
});

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

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

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

स्रोत: स्वचालित रूप से थंबनेल फ़ंक्शन README उत्पन्न करें

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


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


यह उत्तर 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 () फ्रंट एंड से

documentation हमें 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 की समय सीमा समाप्त हो गई थी। मैंने अपने कोड में कई बदलाव किए, और सब कुछ काम किया ... जब तक कि यह सब एक हफ्ते बाद दुर्घटनाग्रस्त नहीं हो गया। यह एक महीने से अधिक की निराशा के लिए चला गया।

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

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

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

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

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

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

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

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

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

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


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

आपको 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].mediaLinkenter

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

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




google-cloud-functions