4
1

More than 3 years have passed since last update.

Firebase Admin SDKでGoogle Cloud Storageに直接画像をアップロードする

Posted at

概要

フロント側からFirebase SDKを利用して画像をアップロードするのではなく、サーバー側でFirebase Admin SDKを利用して画像を直接アップロードする方法に関して試行錯誤したので、備忘録として残す

前提

Firebase SDKで画像をアップロードするには

以下の公式ドキュメントに書かれているように、Firebas SDKを利用して、Blob, File,バイト配列など様々な形式からファイルをアップロードすることができる
ただし、サーバー側ではFirebase SDKは使えず、Firebase Admin SDKを利用する必要がある

// Fileからアップロードする例
async uploadFile(file: File) {
      const path = 'cloud_storage_path';

      try {
        const ref = this.$firebase.storage().ref();
        const imgRef = ref.child(path);
        await imgRef.put(file);
      } catch (err) {
        console.error(err);
        alert('画像のアップロードに失敗しました');
      }
    }
  }

Firebase Admin SDKで画像をアップロードするには

Firebase Admin SDKでは

という2つの方法がある
今回はローカルに一時ファイルを作成せずに、直接アップロードする方法を採用する

Firebase Admin SDKでGoogle Cloud Storageに直接ファイルをアップロードする方法

結果としては以下のコードで直接ファイルをアップロードを実現できた

サーバー側

async uploadFile(content: StorageUploadContent) {
    try {
      const bucket = admin.storage().bucket('bucket_name');
      const file = bucket.file('cloud_storage_path');
      const buffer = Buffer.from(content.file, 'base64');

      await file.save(buffer, {
        metadata: {
          contentType: content.type,
        },
      });
    } catch (err) {
      console.error(err);
      throw err;
    }
  }

フロント側

async uploadFile(file: File) {
      const path = 'cloud_storage_path';
      const reader = new FileReader();

      reader.onload = async () => {
        const arrayBuffer = new Uint8Array(reader.result as ArrayBuffer);
        // ArrayBufferからbase64文字列に変換
        const base64 = btoa(
          arrayBuffer.reduce((p, c) => {
            return p + String.fromCharCode(c);
          }, '')
        );
        const content: StorageUploadContent = { file: base64, type: file.type, path };

        try {
      // 自前で作成したAPIを叩く
          await this.$storage.uploadContent(content);
        } catch (err) {
          console.error(err);
          alert('画像のアップロードに失敗しました');
        }
      };

      await reader.readAsArrayBuffer(file);
    }

詰まったところ

File型ではFile.save()ができない

Firebase SDK同様にFile型をそのまま渡してアップロードしようとしていたが、
TypeError: The "chunk" argument must be one of type string or Buffer. Received type object...
というエラーが出るので、File型ではアップロードができない

File型をバイナリ文字列でアップロードすると画像がうまく保存されない

File型をFileReader.readAsBinaryString()でバイナリ文字列に変換してアップロードしたところ、アップロードには成功するが画像が表示されない

File型をbase64文字列でアップロードすると画像がうまく保存されない

バイナリ文字列に変換した場合と同様の結果となった
must be one of type stringとはどんな文字列なんだろか?
結果としてはbase64文字列をフロント側から渡して、サーバー側でデコードしてFile.save()に渡すようにした

4
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1