JavaScript
angular
Firebase
FirebaseStorage

AngularでCloud Storage for Firebaseにファイルアップロード

AngluarからFirebase SDKを使ってファイル(画像)のアップロードを試してみます。
AngularにはAngluarFireという公式ライブラリが用意されていいますが、今のところCloud Storageを扱えるAPIは用意されていないので、JavaScriptのSDKを使いました。
Proposal: AngularFireStorage #940を見る限りもうすぐ実装されそうな気もしますが...

前提

  • Firebaseのアカウントを取得済み(無料枠で可)
  • Firebaseのプロジェクトは作成済み
  • Angularのプロジェクトは作成済み

サンプル実装

Firebaseの設定

事前にCloud Storageを利用を有効にしておく必要があるので、コンソールの「Storage」から「スタートガイド」を選択します。

storage_01.png

セキュリティルールの確認画面が表示されるので、「OK」をクリックします。

storage_02.png

次に、「ルール」タブからセキュリティルールを次のように編集します。
※ テスト的に認証無しでバケットのRead、Writeが行えるように修正

service firebase.storage {
  match /b/{bucket}/o {
    match /{allPaths=**} {
      // allow read, write: if request.auth != null;
      allow read, write: if true;
    }
  }
}

最後に、画面右上の「ウェブ設定」をクリックし表示される設定情報のスニペットのうち次の部分をコピーしておきます。

storage_03.png

今回試すCloud Storageとは関係ない設定項目も含まれていますが、ガスっとコピーしてしまいます。

設定情報
    apiKey: '<your-key>',
    authDomain: '<your-project-authdomain>',
    databaseURL: '<your-database-URL>',
    projectId: '<your-project-id>',
    storageBucket: '<your-storage-bucket>',
    messagingSenderId: '<your-messaging-sender-id>'

firebaseのインストール

冒頭にもある通りAngluarFireではなく、JavaScriptのSDKのfirebaseを使います。

$ npm install --save firebase

アップロード機能を実装するコンポーネントで次のようにインポートしておきます。

file-upload.component.ts
import * as firebase from 'firebase';

src/environments/environment.tsを開き、「Firebaseの設定」で取得した設定情報を次のように設定しておきます。

environment.ts
export const environment = {
  production: false,
  firebase: {
    apiKey: '<your-key>',
    authDomain: '<your-project-authdomain>',
    databaseURL: '<your-database-URL>',
    projectId: '<your-project-id>',
    messagingSenderId: '<your-messaging-sender-id>'
  }
};

ファイルアップロードの実装

まずは、コンストラクタ内でfirebaseにプロジェクト情報を設定します。

file-upload.component.ts
...
import * as firebase from 'firebase';
import { environment } from './../../environments/environment';

...
  constructor() {
    firebase.initializeApp(environment.firebase);
  }
...

コンポーネントのHTMLテンプレート側です。

inputのchangeイベントにonChangeInput()メソッドをバインドして、ファイル選択がされた際は、即時アップロード処理が呼ばれるようにしています。

file-upload.component.html
<h1>ファイルアップロード🐶</h1>

<!-- テキストファイルを選択するinput -->
<div id="input-area">
  <input type="file" accept="image/*" (change)="onChangeInput($event)">
</div>

<!-- アップロードしたファイルを表示するエリア -->
<img [src]="uploadResult?.downloadURL || ''">

次に、コンポーネントのクラス側です(一部省略)。

file-upload.component.ts
...
  // ファイルのURLを含むアップロード結果
  public uploadResult: any = null;

  constructor() {
    firebase.initializeApp(environment.firebase);
  }

  onChangeInput(evt) {
    const file = evt.target.files[0];

    // フォルダ名、ファイル名を指定して参照を作成する
    const storageRef = firebase.storage().ref(`upload_files/${file.name}`);

    // putメソッドでファイルをアップロード
    // 結果はPromiseで取得可能
    storageRef.put(file).then(result => {
      // ここではアップロー済みの画像を表示するため結果をメンバ変数に格納
      this.uploadResult = result;
    })
    .catch(err => console.log(err));
  }

HTML5のinputで取得した、Fileオブジェクトをそのまま扱えるのは便利ですね。
Fileの他にBlob、Uint8Arrayのアップロードにも対応しているようです。

確認

開発サーバーでAngularアプリを立ち上げて、確認してみます。

$ ng serve

適当な画像ファイルを選択すると...
アップロード結果に含まれるダウンロードURLから読み込んだ画像が表示されます。

スクリーンショット 2017-11-29 22.32.09.png

Firebaseのコンソールからも、アップロード済みのファイルが確認できました。
スクリーンショット 2017-11-29 22.33.06.png

ほんの数行でファイルアップロードが実装できるのすごい...
今回はAngularで試しましたが、使っているはJavaScriptのSDKなので、ピュアのJavaScriptや他のJavaScriptフレームワークでも同様に実装できるかと思います。

以上です。

参考

https://firebase.google.com/docs/storage/web/start?hl=ja