visible true

技術的なメモを書く

React NativeでFirebase Storageに画像を上げるときにputStringが上手くいかないのでbase-64を入れてatob関数を補完する

React Nativeを、ペーパープロトタイピングprottなどを使ったモックアッププロトタイピングの次のフェーズとして動くプロトタイピングツールに使えないかなぁと思ってちょこちょこ触ってます。

うまくいくと両ユーザ向けに同時に動くプロトタイプを提供できてフィードバックが捗るのとAndroidiOSの両方のチームで同時に一つの仕様をいじれるので仮説や価値の理解や共有らなんやら色々捗るんじゃないかなぁとか思ってます。

バックエンド側もFirebaseを使うと結構カジュアルに色々やれそうだな〜とか思っていて色々試し始めたんですがFirebase Storageにデバイス上の画像をアップロードする処理ではまりました。

環境

  • React Native: 0.42.3
  • Firebase: 3.7.3

問題

react-native-image-pickerなんかを使って写真を撮ったりデバイス上の写真を選択すると、ファイル名やContentTypeやbase64に変換された実データを取得できます。次のコードはFirebase StorageにputString関数で画像をアップロードする例です。

firebase.initializeApp(config);
const storage = firebase.storage().ref();

const ref = storage.child(response.fileName);
const metadata = {contentType: response.type};

ref.putString(response.data, 'base64', metadata).then((snapshot) => {
  done();
});

putString関数の第一引数のresponse.dataには画像をbase64に変換した文字列が詰まっており、第二引数はデータフォーマットを示すためにbase64を渡しています。これをReact Nativeで実行すると次のようにInvalid character foundとなります。

f:id:sys1yagi:20170326215741p:plain:w300

どーもよくわからないのでBlobやUint8Arrayを使う方法を試みるも、そもそもReact NativeにはBlobはないらしいという事がわかり、react-native-fetch-blobというBlob周りのポリフィルを提供しているライブラリを導入して試してみるもうまくいかず途方にくれてました。

原因

万策尽きたのでしぶしぶFirebase Storageのクライアントコードを読むことにしました。エラー画面にstacktraceが吐かれてるのでそんなに追いかけるのは難しくなかったです。

f:id:sys1yagi:20170326220926p:plain

こんな感じでtry-catchがあって、atob関数しか呼び出してないのでこれがちゃんと動いてないんだな〜という事がわかりました。

対応

Blobを使ったりするところであれこれ試す中で、

javascript - How to convert base64 into Blob in React Native? - Stack Overflow

とかを試していたのでピンときて、

npm install --save base-64

して(base64)、

const atob = require('base-64').decode;
window.atob = atob;

コンポーネントの冒頭に書いたらうごいた。わいわい。

f:id:sys1yagi:20170326221919p:plain

雑感

React Nativeのポリフィル集ありそうだけどどーなんだろ。 React.parts – A catalog of React componentsとかを眺めていると結構色々あって面白い。一方で改廃も激しいので大変そう。