Cloud Functions for FirebaseでアップロードされたファイルからダウンロードURLを取得する


124

Functions for Firebaseを使用してファイルをFirebase Storageにアップロードした後、ファイルのダウンロードURLを取得したいと思います。

私はこれを持っています:

...

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

        // Get the download url of file

    });

オブジェクトファイルには多くのパラメータがあります。という名前でもmediaLink。ただし、このリンクにアクセスしようとすると、次のエラーが発生します。

匿名ユーザーにはオブジェクトへのstorage.objects.getアクセス権がありません...

誰かがパブリックダウンロードURLを取得する方法を教えてもらえますか?

ありがとうございました


関数で利用可能なデータからURLを再構築するこの投稿も参照してください。
加藤

回答:


133

@ google-cloud / storageからgetSignedURLを使用して署名付きURLを生成する必要があります NPMモジュールます。

例:

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する必要がありますアプリケーションのデフォルトの認証情報では不十分な。

更新:Cloud Storage SDKは、@ google-cloud / storageのラッパーとして機能する Firebase Admin SDKを介してアクセスできるようになりました。唯一の方法は、次のいずれかである場合です。

  1. 特別なサービスアカウントでSDKを初期化します。通常は、2番目のデフォルト以外のインスタンスを使用します。
  2. または、サービスアカウントなしで、デフォルトのApp Engineサービスアカウントに「signBlob」権限を付与します。

74
これは奇妙です。Firebase Android、iOS、Web SDKを使用している場合、ストレージ参照からダウンロードURLを簡単に取得できます。管理者になると、なぜそれほど簡単ではないのですか?PS:gcsの初期化に必要な「service-account.json」はどこにありますか?
Valentin

2
これは、admin-sdkにCloud Storageが追加されていないためです。admin-sdkサービスアカウントjsonは、ここのconsole.firebase.google.com/project/_/settings/serviceaccounts/…から
James Daniels

18
このメソッドで生成されたURLは、途方もなく長いです。@martemorfosisが提案する方法で生成されたURLは、はるかに優れています。そのURLを生成する関数はありますか?これは、firebase-sdkを使用しているときに将来使用するためにデータベースに保存するものです。ミラーメソッドは、関数ドメインに存在する必要があります。
ボガック

3
デプロイされた関数に沿ってservice-account.jsonをアップロードするにはどうすればよいですか?functionsフォルダーに配置して、package.jsonのfileフィールドで参照しようとしましたが、デプロイされていません。ありがとうございました。
David Aroesti

2
追加する必要がactionありexpiresますか?
Chad Bingham

82

アップロード時にダウンロードトークンを指定する方法の例を次に示します。

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

ここで重要なのはmetadatametadataオプションプロパティ内にネストされたオブジェクトがあることです。firebaseStorageDownloadTokensuuid-v4値に設定すると、Cloud Storageはそれをパブリック認証トークンとして使用するようになります。

@martemorfosisに感謝


ストレージに既にアップロードされているファイルの有効なUUIDトークンを取得するにはどうすればよいですか?ランダムなUUIDの生成は役に立ちませんでした。ポインタはありますか?
DerFaizio 2017年

3
答えは@martemorfosisの投稿で見つかりました。UUIDは、object.metadata exports.uploadProfilePic = functions.storage.object()。onChange(event => {const object = event.data; //ストレージオブジェクトから取得できます。constuuid = object.metadata.firebaseStorageDownloadTokens; // ...
DerFaizio 2017年

バケツの例をありがとう!バケットとファイルのメソッドのさまざまな組み合わせをほぼ1時間試しました:)
試しました

1
ご回答有難うございます!私の場合、アップロードの完了時にデータを返さないbucket.file(fileName).createWriteStreamを使用してアップロードしていたため、encodeURIComponent(file.name)ではなくencodeURIComponent(fileName)を使用しました。
Stanislau Buzunko

2
これが正解です。その結果、Firebase SDK(@DevMike)によって生成されたものと同様のURLが得られます。
Samuel E.

64

この回答では、ファイルをGoogle / Firebase Cloud StorageにアップロードするときにダウンロードURLを取得するためのオプションをまとめています。ダウンロードURLには3つのタイプがあります。

  1. 署名付きダウンロードURL。これは一時的なものであり、セキュリティ機能があります。
  2. 永続的でセキュリティ機能を備えたトークンダウンロードURL
  3. 永続的でセキュリティに欠ける公開ダウンロードURL

トークンのダウンロードURLを取得するには3つの方法があります。他の2つのダウンロードURLは、それらを取得する1つの方法しかありません。

Firebase Storageコンソールから

Firebase Storageコンソールからダウンロード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();

これにより、Firebase Storageコンソールから取得できるのと同じダウンロードURLが取得されます。この方法は簡単ですが、比較的単純なデータベース構造のために、ファイルへのパス(このアプリでは約300行のコード)を知っている必要があります。データベースが複雑な場合、これは悪夢になります。また、フロントエンドからファイルをアップロードすることもできますが、これにより、アプリをダウンロードするすべての人に資格情報が公開されます。したがって、ほとんどのプロジェクトでは、NodeバックエンドまたはGoogle Cloud Functionsからファイルをアップロードし、ダウンロードURLを取得して、ファイルに関する他のデータと一緒にデータベースに保存します。

一時ダウンロードURLのgetSignedUrl()

getSignedUrl()は、NodeのバックエンドまたはGoogle Cloud Functionsから簡単に使用できます。

  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は一時的なものであると記載されています。デフォルトの有効期限は1時間、最大有効期限は7日です。

ここで、署名されたURLが1週間で期限切れになることをgetSignedUrlが決して言わないようにします。文書コードには3-17-2025有効期限があり、将来の有効期限を設定できることを示しています。私のアプリは完全に動作し、1週間後にクラッシュしました。エラーメッセージは、署名が一致しなかったことを示しており、ダウンロードURLの有効期限が切れていることを示していません。私はコードにさまざまな変更を加え、すべてが機能しました...すべてが1週間後にクラッシュするまで。これは1か月以上続いた欲求不満でした。

ファイルを公開する

ドキュメントで説明されているように、ファイルの権限を公開読み取りに設定できます。これは、クラウドストレージブラウザまたはノードサーバーから実行できます。1つのファイル、ディレクトリ、またはストレージデータベース全体をパブリックにすることができます。ここにノードコードがあります:

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

結果はCloud Storageブラウザでは次のようになります。

ここに画像の説明を入力してください

だれでも標準パスを使用してファイルをダウンロードできます。

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

ファイルをパブリックにするもう1つの方法は、メソッドmakePublic()を使用することです。これを機能させることができませんでした。バケットとファイルのパスを正しく取得するのは難しいです。

興味深い代替手段は、アクセス制御リストを使用することです。リストに入れたり、使用したユーザーだけがファイルを利用できるようにすることができますauthenticatedRead、Googleアカウントからログインしているすべてのます。「Firebase Authを使用してアプリにログインしたユーザー」というオプションがある場合は、これを使用します。これは、ユーザーのみにアクセスを制限するためです。

firebaseStorageDownloadTokensを使用して独自のダウンロードURLを作成する

いくつかの回答が、文書化されていないGoogle Storageオブジェクトプロパティについて説明していますfirebaseStorageDownloadTokens。これにより、使用したいトークンをストレージに伝えることができます。uuidNodeモジュールでトークンを生成できます。4行のコードで、独自のダウンロードURLを作成できますgetDownloadURL()。これは、コンソールまたはから取得したものと同じダウンロードURLです。4行のコードは次のとおりです。

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:ます。

Doug StevensonさんfirebaseStorageDownloadTokensは、これは公式のGoogle Cloud Storage機能ではないと指摘しました。あなたはそれをどんなGoogleドキュメンテーションでも見つけません、そしてそれが将来のバージョンのであろうという約束はありません@google-cloudfirebaseStorageDownloadTokensそれが私が欲しいものを手に入れる唯一の方法であるので私は好きですが、それは使用するのが安全ではないという「匂い」を持っています。

ノードからgetDownloadURL()がないのはなぜですか?

@Clintonが書いたように、Googleはfile.getDownloadURL()メソッドを作成する必要があり@google-cloud/storageます(つまり、ノードのバックエンド)。Google Cloud Functionsからファイルをアップロードし、トークンのダウンロードURLを取得したいと考えています。


10
私は上の問題が作成され@google-cloud/storage、このために、それは+1に気軽;)github.com/googleapis/nodejs-storage/issues/697
テオ・チャンピオン

1
最新のmakePublic()リンク。
galki

1
firebaseStorageDownloadTokensもう動作しないようです。
メイソン

1
受け入れられた回答は、正しくない有効期限のない永続的なダウンロードURLを取得することは不可能であることを示唆しています。回答の詳細は非常に優れており、正解としてマークする必要があります。ありがとうございました。
DevMike、

2
@thomas素晴らしい要約をありがとう!永続的なトークンダウンロードURLを取得する方法は3つあると説明しましたが、共有したのは2つだけです。(a)Firebase Storage Consoleから、および(b)getDownloadURL()フロントエンドから。3番目の方法は何ですか?
czphilip

23

functions オブジェクトレスポンスの最近の変更により、次のようにダウンロードURLを「ステッチ」するために必要なすべてを取得できます。

 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。これらを取得する方法がわかりません。
Dygerati

また、[バケット]されbucket.name、あなたはそれをハードコーディングや余分なローカルVARを使用する必要はありません
CALINダリエー

4
このソリューションの問題は、サービスURLがハードコードされていることです。Firebase / Googleが変更すると、壊れる可能性があります。metadata.mediaLinkプロパティを使用すると、このような問題を回避できます。
Laurent

2
このようなURLを作成することはサポートされていません。今日は機能するかもしれませんが、将来は機能しなくなる可能性があります。適切なダウンロードURLを生成するには、提供されているAPIのみを使用してください。
Doug Stevenson

1
変更される可能性のあるハードコーディングされたURLに依存することは悪い選択です。
Laurent

23

Firebaseプロジェクトで作業している場合、他のライブラリを含めたり、認証情報ファイルをダウンロードしたりせずに、Cloud Functionで署名付き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. 引き続きAPIコンソールで、メインメニューの[IAMと管理]-> [IAM]に移動します
  3. 「App Engineのデフォルトのサービスアカウント」の役割の[編集]をクリックします
  4. [別の役割を追加]をクリックし、「サービスアカウントトークン作成者」という名前を追加します
  5. 保存して、変更が反映されるまで1分待ちます

通常のFirebase構成では、上記のコードを初めて実行する、エラーが発生します。IDおよびアクセス管理(IAM)APIは、以前はプロジェクトXXXXXXで使用されていないか、無効になっています。。エラーメッセージのリンクをクリックしてIAM APIを有効にすると、別のエラーが発生しますサービスアカウントmy-service-accountでこの操作を実行するには、権限iam.serviceAccounts.signBlobが必要です。トークン作成者の役割を追加すると、この2番目の権限の問題が修正されます。


私は基本的にこれらの同じ詳細で答えを残そうとしていましたが、最終的には難しい方法を見つけました-これまでに解決策をこれまで読んでいたらいいのにと思います:/これは12/12/18の時点で私にとってうまくいきました。詳細な説明をありがとう、私たちの初心者には非常に役立ちます!!
Kat

2
私のsignedurlは2週間で期限切れになりますが、キーなしでadmin.initializeApp()を使用していますが、これは問題ですか?App Engineアプリのデフォルトのサービスアカウントを「所有者」とCloud Functionsサービスエージェントに設定しましたが、今のところ「所有者」を削除して「サービスアカウントトークン作成者」を追加しました
アミットブラボー

2
署名付きURLは7日で期限切れになります。有効期限を短く設定できますが、長くすることはできません。
Thomas David Kehoe

有効期限が切れた場合にURLを更新する方法は?
Manoj MM

より長い時間に設定するためにURLを更新する方法は?
Saifallak

17

私が成功裏に使用している1つの方法firebaseStorageDownloadTokensは、アップロードが完了した後、ファイルのメタデータで指定されたキーにUUID v4値を設定し、FirebaseがこれらのURLを生成するために使用する構造に従ってダウンロードURLを自分でアセンブルすることです。

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

この方法を使用するのにどれだけ「安全」であるかはわかりませんが(Firebaseが将来的にダウンロードURLを生成する方法を変更する可能性がある場合)、実装は簡単です。


1
uuid値を設定する例はありますか?
Drew Beaupre

1
Drewと同じ質問です。メタデータはどこに設定しますか?bucket.upload関数を設定しようとしましたが、機能しませんでした。
Vysakh Sreenivasan

1
Vysakh、私は例付きの完全な回答を投稿しました。お役に立てば幸いです。
Drew Beaupre

トークンをどこでどのように作成しますか?
CodyBugstein

3
私はこの手法を「安全」だとは考えていません。ダウンロードURLは不透明であることが意図されており、そのコンポーネントは分解または組み立てられないためです。
Doug Stevenson

16

Firebase Admin SDKのserviceAccountKey.jsonファイルをどこに置くべきか迷っている人のために。それをfunctionsフォルダーに入れて、いつものようにデプロイします。

それでも、Javascript SDKの場合のように、メタデータからダウンロードURLを取得できないのはなぜでしょうか。最終的に期限切れになるURLを生成してデータベースに保存することは望ましくありません。


15

Cloud Storage 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バーで画像をヒットした場合、インラインで表示する代わりに画像をダウンロードすることです。
Michael Giovanni Pumo

file.getMetadata()は、ファイル参照でsave()メソッドを使用した後、私にとってはうまくいった。NodeJSでfirebase-admin sdkを使用する。
Pascal Lamers 2018

動作しませんでした。匿名の呼び出し元にyour_app / image.jpgへのstorage.objects.getアクセス権がありません
Manoj MM

9

申し訳ありませんが、評判がないため上記の質問にコメントを投稿できません。そのため、この回答に含めます。

上記のように署名付きURLを生成しますが、service-account.jsonを使用する代わりに、生成できるserviceAccountKey.jsonを使用する必要があると思います(それに応じてYOURPROJECTIDを置き換えてください)。

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を配布することは、多くの場合、かなり悪く危険な可能性があります。Firebaseのドキュメントによると、署名されたURLはしばらくすると期限切れになるため、それをデータベースに追加すると、特定の時間枠の後に空のURLが表示されます

そこにあるドキュメントを誤解しており、署名付きURLの有効期限が切れていない可能性があります。その結果、セキュリティ上の問題が発生する可能性があります。キーは、アップロードされたすべてのファイルで同じようです。これは、1つのファイルのURLを取得すると、その名前を知るだけで、誰かがアクセスするように強制されていないファイルに簡単にアクセスできることを意味します。

私がそれを誤解した場合、私は修正されることになります。それ以外の場合は、おそらく上記の名前のソリューションを更新する必要があります。そこが間違っているかもしれない


7

これは私が現在使用しているもので、シンプルで完璧に動作します。

Google Cloudで何もする必要はありません。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

更新:

メタデータを取得するためにアップロードメソッドで2つの異なる呼び出しを行う必要はありません。

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

1
base64エンコードされていないファイルでどのように使用しますか?
Tibor Udvari

1
mediaLinkenterではなく、ただのmediaLink
l2aelba

1
私はメディアリンクを見つけることができませんi.stack.imgur.com/B4Fw5.png
サラ

@Sarah私はtypescriptを使ってこれを書きました、モジュールの置き換えがあるかどうかはわかりません。
Oliver Dixon

3

同じ問題がありましたが、READMEではなく、firebase関数の例のコードを見ていました。そして、このスレッドの回答も役に立ちませんでした...

次のようにすることで、設定ファイルを渡さないようにすることができます。

プロジェクトのCloud Console> IAMと管理者> IAMに移動し、App Engineのデフォルトのサービスアカウントを見つけて、そのメンバーにサービスアカウントトークン作成者の役割を追加します。これにより、アプリは画像への署名済みパブリックURLを作成できます。

ソース:サムネイル機能の自動生成README

App Engineの役割は次のようになります。

クラウドコンソール


3

事前定義されたアクセス制御リストの値「publicRead」を使用する場合、ファイルをアップロードして、非常に単純なURL構造でアクセスできます。

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

これは、単純なURLを持つ公開ファイルが必要な場合にのみ機能します。これにより、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- 秘密鍵生成し、 / functionsフォルダーに配置します。

2-コードを次のように構成します。

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

ドキュメンテーション

try / catchは、他のファイルをインポートし、各ファイルに1つの関数を作成するindex.jsを使用しているためです。すべての関数で単一のindex.jsファイルを使用している場合は、で問題ありませんadmin.initializeApp(Object.assign(functions.config().firebase, { credential: admin.credential.cert(serviceAccount) }));


私にとっては「../serviceaccountkey.json」でしたが、.. /を使用してくれてありがとう
robert king

1

firebase 6.0.0以降、次のように管理者を使用してストレージに直接アクセスできました。

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

したがって、サービスアカウントを追加する必要はありませんでした。次に、上で参照したようにUUIDを設定すると、firebaseの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 Cloud Functions:require(…)は関数ではありません

これを試して:

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を使用して、base64でエンコードされた画像(文字列)をGoogle Cloud Storageバケットに直接アップロードするにはどうすればよいですか?

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);
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.