계속: ReactNative (Expo)로 카메라로 찍은 사진을 Firebase Storage에 저장
18022 단어 reactnativeFirebaseexpo
주요 흐름
Expo + Firebase를 이용한 업로드 처리는 다음과 같습니다.
샘플 사양
버튼이나 배치하는 것이 귀찮기 때문에 reac-native-elements의 Avatar를 이용하여 이미지의 선택, 표시를 해 봅니다.
뭐 Profile 이미지라든지라도 사용합니다. Image라든지 같습니다 (코멘트 아웃 해 넣고 있습니다).
이치오우 프로그레스라도 집어 봅니다.
구현
필수 모듈 설치
심플한 것에 여러가지 사용하고 있습니다.
npm install --save expo-constants expo-permissions expo-image-picker
npm install --save firebase react-native-elements
Firebase
Firebase에 등록하고 프로젝트를 만드는 것은 당연히 App.js와 같은 계층에 Firebase.js를 설치하고 다음과 같이하고 있습니다.
Config 정보는 각자의 환경에 맞춥니다.
Firebase.js
import firebase from 'firebase';
const firebaseConfig = {
apiKey: "xxxxxxxxxxxxxxxxxxxxxxxxxxx",
authDomain: "xxxxxxxx.firebaseapp.com",
databaseURL: "https://xxxxxxxx.firebaseio.com",
projectId: "xxxxxxxxx",
storageBucket: "xxxxxxxxx.appspot.com",
messagingSenderId: "xxxxxxxxxx",
appId: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
measurementId: "xxxxxxxxx"
};
firebase.initializeApp(firebaseConfig);
export default firebase;
구현
흐름을 알 수 있도록 하나의 함수로 구현하고 있습니다.
이전에 구현했을 때 Permission은 CAMERA_ROLL을 얻어야했지만 이번에는 CAMERA가 아니라면 오류가 발생했습니다.
App.js
import React from 'react';
import { StyleSheet, Text, View, Image } from 'react-native';
import { Avatar, Button } from 'react-native-elements';
import firebase from './Firebase';
import Constants from 'expo-constants';
import * as ImagePicker from 'expo-image-picker';
import * as Permissions from 'expo-permissions';
class App extends React.Component {
state = {
url: 'https://firebasestorage.googleapis.com/v0/b/test-fc01e.appspot.com/o/noimage.png?alt=media&token=0606e1b4-e817-4859-83d4-7920c99e14c0',
progress: '',
}
ImageChoiceAndUpload = async () => {
try {
//まず、CAMERA_ROLLのパーミッション確認
if (Constants.platform.ios) {
const { status } = await Permissions.askAsync(Permissions.CAMERA);
if (status !== 'granted') {
alert("利用には許可が必要です。");
return;
}
}
//次に、画像を選ぶ
const result = await ImagePicker.launchCameraAsync();
if (!result.cancelled) {
//撮影された(ローカルの)写真を取得
const localUri = await fetch(result.uri);
//blobを取得
const localBlob = await localUri.blob();
//filename 実際はUIDとかユーザー固有のIDをファイル名にする感じかと
const filename = "profileImage"
//firebase storeのrefを取得
const storageRef = firebase.storage().ref().child("images/" + filename);
//upload
// const putTask = await storageRef.put(localBlob);
//進捗を取得したいのでawaitは使わず
const putTask = storageRef.put(localBlob);
putTask.on('state_changed', (snapshot) => {
let progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
this.setState({
progress: parseInt(progress) + "%",
});
}, (error) => {
console.log(error);
alert("アップロードに失敗しました。サイズが大きいとか。");
}, () => {
putTask.snapshot.ref.getDownloadURL().then(downloadURL => {
console.log(downloadURL);
this.setState({
progress: '',
url: downloadURL,
});
})
})
}
} catch (e) {
console.log(e.message);
alert("サイズが多き過ぎるかも。");
}
}
render() {
return (
<View style={{ marginTop: 100, alignSelf: 'center' }}>
<Text>画像アップロード</Text>
<View style={{ margin: 20 }}>
<Avatar
size="large"
rounded
title="NI"
onPress={this.ImageChoiceAndUpload}
source={{ uri: this.state.url }}
/>
<Text style={{ alignSelf: 'center' }}>{this.state.progress}</Text>
</View>
{/* <Image
source={{ uri: this.state.url }}
style={{ width: 100, height: 100, alignSelf: 'center' }}
/> */}
</View>
);
}
}
export default App;
기타
업로드의 용량 제한등을 하고 싶은 곳입니다만, Storage의 룰을 사용할 수도 있는 것 같습니다. 그리고는 extension의 resize라도 좋을지도 모릅니다.
service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
allow read;
allow write: if request.resource.size < 3 * 1024 * 1024; //3Mまで
}
}
}
Reference
이 문제에 관하여(계속: ReactNative (Expo)로 카메라로 찍은 사진을 Firebase Storage에 저장), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/zaburo/items/729f145735ecdc5c660c텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)