質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.02%

[node.js]Firebase storageにアップロードできない(firebase is not defined)

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 1,903

yoshiky

score 105

お世話になってます。
ネット上から画像を取得し、Firebase Storageに保存するアプリをFirebase functionsで動かしたいのですが、Storageへのアップロードができずに困っております。

 やりたいこと
  • 画像提供サービスからAPI経由で画像情報を取得
  • 取得した画像をFirebase Storageに保存
 できないこと
  • Firebase Storageへのアップロード
 書いたソースコード
$ node -v
v8.7.0
$ firebase -V
4.2.1
//const firebase = require('firebase');  // <=コメントアウトしても結果は変わらず
const functions = require('firebase-functions');
const admin = require('firebase-admin');
const rp = require('request-promise');

const path = require('path');
const os = require('os');
const fs = require('fs');

const config = {
    apiKey: "xxx",
    authDomain: "xxx.firebaseapp.com",
    databaseURL: "https://xxx.firebaseio.com",
    projectId: "xxx",
    storageBucket: "xxx.appspot.com",
    messagingSenderId: "00000000"
  };
firebase.initializeApp(config);
const storageRef = firebase.storage().ref();
const fileRef = storageRef.child('test.jpg');

const options = {
    uri: 'https://xxx',
};

const tmpFile = path.join(os.tmpdir(), 'test.jpg');

exports.api = functions.https.onRequest((request, response) => {
    async function main(){
        // 画像情報を取得
        const photoInfo = await getPhotoInfo();
        const photo = photoInfo.info.photo[0];
        const fileName = photo['image_url'].split('/').pop();
        const fileUrl = photo['image_url'];

        // 画像をダウンロード
        await downloadPhoto(fileUrl, fileName);
        // ダウンロードできたか確認。console出力されるのでダウンロードはできているはず
        fs.exists(tmpFile, exists => {
            if(exists){
                console.log('exist downloaded file.');
            }
        })

        // 画像をアップロード
        fileRef.put(tmpFile).then(function(snapshot) {
            console.log('Uploaded file!');
        });
    }

    main();

    async function getPhotoInfo() {
        const result = await rp(options);
        return JSON.parse(result);
    }

    async function downloadPhoto(fileUrl, fileName) {
        await rp(fileUrl)
            .then(response => {
                const writeStream = fs.createWriteStream(tmpFile);
                writeStream.write(response, (err) => {
                    if(err) {
                        console.log(err);
                    }
                });
            });
    }

    response.send("Send successfully");
});
 実行結果

firebase-toolsを使い$ firebase serve --only functionsで実行すると
ReferenceError: firebase is not defined
となり起動しない

 聞きたいこと
  • アップロードの仕方

※1投稿1質問が基本かもしれませんが、、可能であれば下記も教えて頂けるとありがたいです。

  • Admin SDKについて
    公式サイトにはFirebase Storageの扱いは2方法掲載されています。
    ウェブでファイルをアップロードする
    Admin Cloud Storage API の概要
    Adminの方は「特権環境から Google Cloud Storage バケットに直接アクセスできます。」と説明がありますが、特権環境ということは管理者用のアプリのみで、ユーザに後悔するアプリでは使わない方がいい、くらいの意味なのでしょうか。

  • Firebase StorageとGoogle Cloud Storageの違い
    もともとFirebaseは独立したサービスだったが、Googleに買収されて以降はGCPからFirebaseが操作できたり、両者の親和性が高まっている、くらいの理解なのですが、よく「Firebase storage upload」で検索すると「Google Cloud Storage」へアップロードしている記事を見かけるので、もしかして同じ?Admin SDKの方にもFirebaseのサイトなのに「Google Cloud Storage バケットに直接アクセスできます。」という説明があります。。

根本的な部分の理解が乏しいのでお恥ずかしいですが、アドバイスを頂けると幸いです。
よろしくお願い申し上げます。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

0

以下のようにしてください。

firebase.initializeApp(config);
↓
admin.initializeApp();

何かの記事を参考にされたと思うのですが、ちゃんと公式ドキュメントを確認しましょう。
https://firebase.google.com/docs/functions/get-started?hl=ja#header

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/11/04 14:14

    ご回答ありがとうございます。下記のようにしたらアップロードされました!
    オプションの指定が甘いのか、真っ黒な小さい画像となってしまいましたが。

    const admin = require('firebase-admin');
    admin.initializeApp();
    const bucket = admin.storage().bucket();

    bucket.upload(tmpFile).then(res => {
    console.log(res);
    })

    ちなみにfirebase.storage().ref();も公式に乗っている書き方ですが、何故ダメなのかご存知でしょうか。
    https://firebase.google.com/docs/storage/web/upload-files?hl=ja

    キャンセル

  • 2018/11/04 15:38

    「firebase.storage()」もでしたね。見逃してました。。。

    > firebase.storage().ref();も公式に乗っている書き方ですが、何故ダメなのかご存知でしょうか。

    「firebase = require('firebase')」が使えないのは、単純にFirebase SDKを追加していないからだと思いますよ。
    https://firebase.google.com/docs/web/setup?hl=ja#prerequisites

    質問内容的に確認しませんでしたが、firebase-toolsを使ってfunctionsの初期化をされたのではないでしょうか。

    上記ドキュメントの冒頭にも記載されている通り、特権環境(サーバーやCloud Functions)から利用する場合はAdmin SDKの利用が推奨されています。

    なので、firebase-toolsを使って初期化された場合は、Firebase SDKではなくAdminSDKが自動的に含まれることになります。

    キャンセル

  • 2018/11/04 19:44

    ありがとうございます!

    > Firebase SDKを追加していないから
    > firebase-toolsを使ってfunctionsの初期化をされたのではないでしょうか。

    なるほど、確かにまだfirebase-toolsでしか動かしていないです。
    改めて下記コマンドでインストールしてみたところ、firebase is not defined は出なくなりました。
    npm install firebase @firebase/storage firebase-admin --save

    しかし代わりに firebase.storage().ref(); の部分で
    firebase.storage is not a function
    が出るようになりました。firebase/storageはインストールしているのですが。。
    Admin SDKを使えばエラーは出なくなりますが、、

    > 特権環境(サーバーやCloud Functions)から利用する場合はAdmin SDKの利用が推奨されています。

    失礼しました。見落としていました。サーバサイド(=アプリのユーザが触れない場所)であれば特権環境としてAdmin SDKを、公式ドキュメントにあるような公開HTMLの中にscirptとして含めるのであればfirebase.storage().ref()などを使う、というような使いわけ?と理解しました。

    キャンセル

  • 2018/11/04 19:49

    失礼しました。
    require("firebase/storage");
    を忘れていました。
    (別の箇所でエラーにはなりましたが、とりあえず firebase serve --only functions でエラーなく起動してくれました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.02%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる