React + Firebaseでの画像アップロードが分かりづらかったのでまとめておきます。
FirebaseのCloud Storageというサービスを利用して画像を保存します。
Contents
手順
画像アップロードだけでも以下の手順が必要です。
ポイント
Firebaseのプロジェクトは事前に作成して下さい。
- Firebase Cloud Storageを作成
- 権限の変更
- プロジェクトにアプリを追加
- 必要なmoduleをインポート
- アプリにSDKを追加
- フォームを用意
- アップロード処理
一つずつ解説します。
設定&実装
Firebase Cloud Storageを作成
Firebaseのプロジェクト画面からCloud Storageを作成します。

「始める」ボタンを押します。

権限に関する注意が出てきます。そのまま「次へ」ボタンでOK。

Cloud Storageのロケーションを選択します。ロケーションは後から変更できないので注意が必要ですが、とりあえず近い場所(asia northeast)を選択しておきます。

権限の変更
本来きちんと認証が出来るようにしてからアップロードの処理を書くべきなのですが、今回はアップロード処理のテストが目的のため、認証をせず誰でもアップロードできるようにします。

if request.auth != null;の部分をif true;とします。
注意ポイント
確認のとき以外は認証を戻しておきましょう。
プロジェクトにアプリを追加
アップロードにはSDKと呼ばれるものを使う必要があるのですが、その取得のためにプロジェクトにアプリを追加します。
メニュー左上の歯車アイコンから「プロジェクトの設定」を選ぶと下の方にアプリを追加するアイコンがあります。そこからアプリを追加しましょう。
アプリのニックネームを聞かれますが、適当で大丈夫です。

追加するときに以下のようなコードが表示されます。後で使用するのでコピーしておきましょう。

必要なmoduleをインポート
React内でfirebaseを使うため、firebaseのパッケージをインストールします。
yarn add firebase
アプリにSDKを追加
firebaseの設定ファイルを作成します。
firebaseフォルダを作成し、firebase.jsを作成。上でアプリを追加した際に表示されたコードの中のfirebaseConfig部分をコピペして下さい。
firebaseConfig以外はこのようにします。
import firebase from "firebase/app";
import "firebase/storage";
var firebaseConfig = {
// ここに自分のプロジェクトのconfigをペースト
};
// Initialize Firebase
firebase.initializeApp(firebaseConfig);
export const storage = firebase.storage();
export default firebase;
補足
firebaseConfigはメニュー左上の「Project Overview」のアイコンから「プロジェクトの設定」を選ぶと確認できます。(下の方にスクロールするとFirebase SDK snippetがある)
フォームを用意
Reactでフォームを作成します。特別なフォームは必要ありません。type="file"として下さい。
<div className="App">
<h1>画像アップロード</h1>
<form onSubmit={onSubmit}>
<input type="file" onChange={handleImage} />
<button>Upload</button>
</form>
<img src={imageUrl} alt="uploaded" />
</div>imgタグはアップロードしたファイルが表示できるようにするためのものです。
アップロード処理
まず最初にアップロード処理のコード全体を書いておきます。下で解説します。
import React, { useState } from "react";
import firebase, { storage } from "./firebase/firebase";
import "./App.css";
function App() {
const [image, setImage] = useState("");
const [imageUrl, setImageUrl] = useState("");
const handleImage = event => {
const image = event.target.files[0];
setImage(image);
};
const onSubmit = event => {
event.preventDefault();
if (image === "") {
console.log("ファイルが選択されていません");
}
// アップロード処理
const uploadTask = storage.ref(`/images/${image.name}`).put(image);
uploadTask.on(
firebase.storage.TaskEvent.STATE_CHANGED,
next,
error,
complete
);
};
const next = snapshot => {
// 進行中のsnapshotを得る
// アップロードの進行度を表示
const percent = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
console.log(percent + "% done");
console.log(snapshot);
};
const error = error => {
// エラーハンドリング
console.log(error);
};
const complete = () => {
// 完了後の処理
// 画像表示のため、アップロードした画像のURLを取得
storage
.ref("images")
.child(image.name)
.getDownloadURL()
.then(fireBaseUrl => {
setImageUrl(fireBaseUrl);
});
};
return (
<div className="App">
<h1>画像アップロード</h1>
<form onSubmit={onSubmit}>
<input type="file" onChange={handleImage} />
<button>Upload</button>
</form>
<img src={imageUrl} alt="uploaded" />
</div>
);
}
export default App;
handleImageはファイルが選択されたときにその内容を取得します。実際のアップロード処理がonSubmitです。
onSubmitの中で重要な部分は以下の部分です。
const uploadTask = storage.ref(`/images/${image.name}`).put(image);
uploadTask.on(
firebase.storage.TaskEvent.STATE_CHANGED,
next,
error,
complete
);storage.ref(`/images/${image.name}`)の部分でアップロード先のフォルダ+ファイル名を指定、その後putメソッドに画像ファイルを渡すことでアップロードできます。
uploadTask.on( ~~~の部分で関数を渡していますが、.onにはnext, error, completeの3つのコールバックを指定できます。
ポイント
nextはアップロードの進行度や状態を取得するための関数で、errorがエラーが起きたときの処理、completeがアップロード成功後の処理です。
上のコードではcompleteコールバック内でアップロードした画像のURLを取得しています。このURLを使って画像の表示を行っています。
以上で実装は終了です。
アップロードしてみると、このようにファイルが表示されます。

ブラウザからfirebaseのstorageにアクセスすれば画像がアップロードされていることも確認できるはずです。
参考↓
まとめ
今回はReactでFirebaseのcloud storageに画像をアップロードしました。
ちょっと面倒ですが、無料で使えるので有効活用したいですね。
認証を絡めた処理は省略してしまったのでアプリを作っていく記事などで扱いたいです。

