RN(expo)でカメラで写真をとってfirestoreに保存する


自分用のメモ。

こちらの記事は古いのでこちらをどうぞ。

注意

このコードにはFirebase Authで認証している箇所がないので、Firestore側のパーミションが下記のように誰でも書き込みOKとなっている必要があります(よくないです)。

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

で、実装。めんどくさいのでApp.jsに全部書いた。

App.js
import React from 'react';
import { StyleSheet, Text, View, Button } from 'react-native';
import * as firebase from 'firebase';
import 'firebase/firestore';
import * as ImagePicker from 'expo-image-picker';
import Constants from 'expo-constants';
import * as Permissions from 'expo-permissions';

const firebaseConfig = {
    apiKey: "xxxxxxxxxxx",
    authDomain: "xxxxxxxxxxx",
    databaseURL: "xxxxxxxxxxx",
    projectId: "xxxxxxxxxxx",
    storageBucket: "xxxxxxxxxxx",
    messagingSenderId: "xxxxxxxxxxx",
    appId: "xxxxxxxxxxx"
};

firebase.initializeApp(firebaseConfig);
const db = firebase.firestore();

export default class App extends React.Component {

    componentDidMount = () => {
        this.getPermissionAsync();
    }

    getPermissionAsync = async () => {
        if (Constants.platform.ios) {
            const { status } = await Permissions.askAsync(Permissions.CAMERA_ROLL);
            if (status !== 'granted') {
                alert('カメラ利用の許可が必要です。')
            }
        }
    }

    onChooseImagePress = async () => {
        let result = await ImagePicker.launchCameraAsync();
        //ライブラリから選ぶ場合
        // let result = await ImagePicker.launchImageLibraryAsyn();

        if (!result.cancelled) {
            this.uploadImage(result.uri, "test-image")
                .then(() => {
                    alert("success");
                })
                .catch(e => {
                    alert(JSON.stringify(e));
                })
        }
    }

    uploadImage = async (uri, imageName) => {

        //元のファイルからblobを生成
        const response = await fetch(uri);
        const blob = await response.blob();

        //firestoreの保存場所指定
        var ref = firebase.storage().ref().child("images/" + imageName);

        //保存場所にput
        return ref.put(blob);
    }
    render() {
        return (
            <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
                <Text>App</Text>
                <Button
                    title="Choose image..."
                    onPress={() => this.onChooseImagePress()}
                />
            </View>
        );
    }
}