【コピペOK】Firebase Storageで画像表示する方法を解説

Firebase プログラミング

こんにちは、はるです。

悩み顔1

プログラマー Firebase の Cloud Storageで画像表示する方法を知りたい。Firebase Hosting Setup Completeが出てきて公式サイトを見てもよく分からなかったので、分かりやすく解説してほしい。

こんな悩みを解決していきます。

記事の内容

  • Firebase Storageで画像表示する方法
  • 全体のソースコード

私は3か月ぐらいfirebaseを使ってきまして、firebaseを使った「URLねんが」というサービスを作りました。
URLねんが

当時、Firebase Storageで画像表示する方法がさっぱり分からず謎でした。
諦めず調べて行った結果、何とか表示することができたので、今回は、Firebase Storageで画像表示する方法を解説していきます。

記事の内容

Firebase Storageで画面表示する方法

以下のステップです。

  1. プロジェクトの作成 & firebaseの初期化
  2. セキュリティルール
  3. ファイルの取得
  4. 画像保存場所のファイルパスを作る
  5. アップロードする
  6. ダウンロードして表示する

Cloud Storageがメインのため、「プロジェクトの作成 & firebaseの初期化」は省略します。

分かりやすく説明するために、「アップロードボタンとダウンロードボタンを作り、ボタンを押されたら各処理を開始する」という機能を作っていきます。

先に全体のソースコードを見たい方はこちら。
全体のソースコード

完成画像

Firebase Storageの完成画像

セキュリティルール

まずは、firebase consoleのStorageを開き、始めるを押します。
firebase console

Cloud Storage のセキュリティ保護ルールでは何もせず次へ。
セキュリティ保護ルール

デフォルトではnam5 (us-central)ですが、今回は東京のリージョンを使いたいので、asia-northeast1にします。
Cloud Firestore のロケーション
リージョン選択

いったん、セキュリティルールをread, write両方とも、allowにします。
テスト環境が終わったら、ちゃんと制限をかけるようにしましょう。
firebasestorageのセキュリティルール

ファイルの取得

アップロードボタンを押されたら、初めにinputタグからファイルを取得します。

test.js

const up = document.getElementById("up");
up.addEventListener("click", () => {
  //ファイルの取得
  const file = document.getElementById("fileButton").files[0];
});

画像保存場所のファイルパスを作る

//ファイルの参照
  var storageRef = firebase.storage().ref();

  //ファイルのメタデータ
  var metadata = {
    contentType: "image/*",
  };

アップロードする

//画像ファイルのアップロード
  const uploadTask = storageRef.child("image/" + file.name).put(file, metadata);
  console.log(uploadTask);

シンプルにするならば、上の2行で十分です。

アップロードの進捗状況を調べたり、エラーチェックを追加したりするのであれば、下のコードも追加しておきましょう。
参考: アップロードの進捗状況をモニタリングする

アップロードが終わった後にダウンロードボタンを表示させたいので、if文を追加しました。

  var flg = 0;
  uploadTask.on(
    "state_changed",
    function (snapshot) {
      var progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
      console.log("Upload is " + progress + "% done");
      switch (snapshot.state) {
        case firebase.storage.TaskState.PAUSED: // or 'paused'
          console.log("Upload is paused");
          break;
        case firebase.storage.TaskState.RUNNING: // or 'running'
          console.log("Upload is running");
          break;
      }
      if (progress === 100 && flg === 0) {
        console.log("100%です。");
        var display = document.querySelector(".disN");
        display.classList.replace("disN", "disB");
        flg = 1;
      }
    },
    function (error) {
      switch (error.code) {
        case "storage/unauthorized":
          // User doesn't have permission to access the object
          console.log(
            "目的の操作を行う権限がユーザーにありません。セキュリティ ルールが正しいことをご確認ください。"
          );
          break;

        case "storage/canceled":
          // User canceled the upload
          console.log("ユーザーがオペレーションをキャンセルしました。");
          break;

        case "storage/unknown":
          // Unknown error occurred, inspect error.serverResponse
          console.log("不明なエラーが発生しました。");
          break;
        default:
          console.log("error");
          break;
      }
    }
  );

ダウンロードして表示する

アップロードと同じ、画像保存場所のファイルパスを使います。
この時、メタデータは要らないです。

const down = document.getElementById("down");
down.addEventListener("click", () => {
  const file = document.getElementById("fileButton").files[0];

  var storageRef = firebase.storage().ref();
  const DownloadTask = storageRef.child("image/" + file.name);

  DownloadTask.getDownloadURL().then((downloadURL) => {
    document.getElementById("image").src = downloadURL;
  });
});

全体のソースコード

test.js

//アップロード
const up = document.getElementById("up");
up.addEventListener("click", () => {
  //ファイルの取得
  const file = document.getElementById("fileButton").files[0];
  //ファイルの参照
  var storageRef = firebase.storage().ref();

  //ファイルのメタデータ
  var metadata = {
    contentType: "image/*",
  };
  //画像ファイルのアップロード
  const uploadTask = storageRef.child("image/" + file.name).put(file, metadata);
  console.log(uploadTask);

  var flg = 0;
  uploadTask.on(
    "state_changed",
    function (snapshot) {
      var progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
      console.log("Upload is " + progress + "% done");
      switch (snapshot.state) {
        case firebase.storage.TaskState.PAUSED: // or 'paused'
          console.log("Upload is paused");
          break;
        case firebase.storage.TaskState.RUNNING: // or 'running'
          console.log("Upload is running");
          break;
      }
      if (progress === 100 && flg === 0) {
        console.log("100%です。");
        var display = document.querySelector(".disN");
        display.classList.replace("disN", "disB");
        flg = 1;
      }
    },
    function (error) {
      switch (error.code) {
        case "storage/unauthorized":
          // User doesn't have permission to access the object
          console.log(
            "目的の操作を行う権限がユーザーにありません。セキュリティ ルールが正しいことをご確認ください。"
          );
          break;

        case "storage/canceled":
          // User canceled the upload
          console.log("ユーザーがオペレーションをキャンセルしました。");
          break;

        case "storage/unknown":
          // Unknown error occurred, inspect error.serverResponse
          console.log("不明なエラーが発生しました。");
          break;
        default:
          console.log("error");
          break;
      }
    }
  );
});

//ダウンロード
const down = document.getElementById("down");
down.addEventListener("click", () => {
  //ファイルの取得
  const file = document.getElementById("fileButton").files[0];
  //ファイルの参照
  var storageRef = firebase.storage().ref();
  const DownloadTask = storageRef.child("image/" + file.name);

  //画像ファイルのダウンロード
  DownloadTask.getDownloadURL().then((downloadURL) => {
    document.getElementById("image").src = downloadURL;
  });
});

index.html

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>storage</title>
    <style>
      html,
      body {
        height: 100%;
        margin: 0;
      }
      .container {
        display: flex;
        justify-content: center;
        align-items: center;
        flex-direction: column;
        height: 100%;
      }
      .disN {
        display: none;
      }
      .disB {
        display: block;
      }
      img {
        height: 300px;
        width: auto;
      }
    </style>
  </head>
  <body>
    <div class="container">
      <div><input type="file" name="" id="fileButton" /></div>
      <div>
        <button id="up">アップロード</button>
        <button id="down" class="disN">ダウンロード</button>
      </div>
      <div>
        <p>
          ダウンロードボタンをクリックした後、<br />数秒後に画像が表示されます。
        </p>
        <img id="image" src="" alt="ダウンロード画像です" />
      </div>
    </div>

    <script src="https://www.gstatic.com/firebasejs/8.2.1/firebase-app.js"></script>
    <script src="https://www.gstatic.com/firebasejs/8.2.1/firebase-analytics.js"></script>

    <script>
      var firebaseConfig = {
        apiKey: "○○○○",
        authDomain: "test2-6d6cd.firebaseapp.com",
        projectId: "test2-6d6cd",
        storageBucket: "test2-6d6cd.appspot.com",
        messagingSenderId: "○○○○",
        appId: "○○○○",
        measurementId: "○○○○",
      };
      // Initialize Firebase
      firebase.initializeApp(firebaseConfig);
      firebase.analytics();
    </script>
    <script src="https://www.gstatic.com/firebasejs/7.23.0/firebase-storage.js"></script>
    <script src="test.js"></script>
  </body>
</html>

以上となります。
ご覧いただきありがとうございました。

参考

ウェブでファイルをアップロードする | Firebase

関連

Firebase Authenticationの使い方を解説【FirebaseUI Auth】
Firebase Hostingでデプロイ(deploy)する方法を解説【4ステップ】