はじめに
ExpoでFirebaseを使用する場合、Web版のFirebaseを使用することになると思います。ここで、FirebaseStorageに画像をアップロードする際にいくつもの罠があり、筆者は二日以上溶かしてしまいました。具体的には以下のような罠がありました。
- reactnativeがatob関数に対応していないためstorageが使えない
- storageにbase64エンコード画像をアップロードしたがうまく表示されない
以上の二点に関して、具体的に説明していきます。
1. ImageFormを作成する
class ImageForm extends React.Component {
constructor(props) {
super(props)
}
componentDidMount() {
this.getPermissionAsync();
}
getPermissionAsync = async () => {
if (Constants.platform.ios) {
const { status } = await Permissions.askAsync(Permissions.CAMERA_ROLL);
if (status !== 'granted') {
alert('Sorry, we need camera roll permissions to make this work!');
}
}
}
_pickImage = async () => {
let result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.All,
allowsEditing: true,
aspect: [4, 3],
base64: true,
quality: 0.5
});
console.log(result);
if (!result.cancelled) {
var uris = this.props.uris
const uri = result.uri
uris.push(uri)
//
}
};
render() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text >{this.props.title}</Text>
<Button
title="Pick an image from camera roll"
onPress={this._pickImage}
/>
</View>
);
}
}
iphoneで使用できるようにするため、getPermissionAsyncをする必要があります。
Buttonを押すと画像をPickすることができ、そのURLをurlsに格納しています。
このurlsをprops等に保存しといてください。
2. firebase storage に画像をアップデート
筆者はredux-sagaとredux-saga-firebaseを使って非同期処理を行なっています。流れとしては、pickした際の画像uriから画像データをfetchしてblobデータを取得。それをアップロードします。
function fetchImage(fileData){
return fetch(fileData)
.then(results => {
const blob = results._bodyBlob;
return blob
})
.catch(error => {
console.log("error" , error)
})
}
export function* uploadImageToStorage({uris}){
var filePath = "/image300"
const uri = uris[0]
const blob = yield call(fetchImage, uri)
const metadata = {contentType: "image/jpeg"}
yield call(storage.uploadFile, filePath, blob, metadata)
以上のソースコードをsaga内に置くことでできるようになります。
発生する罠・エラー
atob関数に対応していない
[base-64]ライブラリをインストールしてnode-moduleに直接書き込みます
npm install -s base-64
/node-modules/redux-saga-firebase/storage.js
const atob = require('base-64').decode;
window.atob = atob;
putStringやuploadStringでbase64を直接アップロードしたが、base64とフォーマットが違う、もしくはプレビューが表示されない
ここでかなり時間をつかいました。一番の対応策はbase64を直接アップロードするのではなく、Blob型にしてアップロードすることだとおもいます。上のやり方でできるとおもうのでやってみてください。
参考URL