mirror of
https://github.com/zhigang1992/examples.git
synced 2026-01-12 22:47:03 +08:00
Merge pull request #96 from byCedric/feat/firebase-storage-upload
feat: add firebase storage upload example
This commit is contained in:
205
with-firebase-storage-upload/App.js
Normal file
205
with-firebase-storage-upload/App.js
Normal file
@@ -0,0 +1,205 @@
|
||||
import * as ImagePicker from 'expo-image-picker';
|
||||
import * as Permissions from 'expo-permissions';
|
||||
import * as firebase from 'firebase';
|
||||
import React from 'react';
|
||||
import {
|
||||
ActivityIndicator,
|
||||
Button,
|
||||
Clipboard,
|
||||
Image,
|
||||
Share,
|
||||
StatusBar,
|
||||
StyleSheet,
|
||||
Text,
|
||||
View,
|
||||
} from 'react-native';
|
||||
import uuid from 'uuid';
|
||||
|
||||
const firebaseConfig = {
|
||||
apiKey: 'AIzaSyAlZruO2T_JNOWn4ysfX6AryR6Dzm_VVaA',
|
||||
authDomain: 'blobtest-36ff6.firebaseapp.com',
|
||||
databaseURL: 'https://blobtest-36ff6.firebaseio.com',
|
||||
storageBucket: 'blobtest-36ff6.appspot.com',
|
||||
messagingSenderId: '506017999540',
|
||||
};
|
||||
|
||||
if (!firebase.apps.length) {
|
||||
firebase.initializeApp(firebaseConfig);
|
||||
}
|
||||
|
||||
// Firebase sets some timeers for a long period, which will trigger some warnings. Let's turn that off for this example
|
||||
console.disableYellowBox = true;
|
||||
|
||||
export default class App extends React.Component {
|
||||
state = {
|
||||
image: null,
|
||||
uploading: false,
|
||||
};
|
||||
|
||||
async componentDidMount() {
|
||||
await Permissions.askAsync(Permissions.CAMERA_ROLL);
|
||||
await Permissions.askAsync(Permissions.CAMERA);
|
||||
}
|
||||
|
||||
render() {
|
||||
let { image } = this.state;
|
||||
|
||||
return (
|
||||
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
|
||||
{!!image && (
|
||||
<Text
|
||||
style={{
|
||||
fontSize: 20,
|
||||
marginBottom: 20,
|
||||
textAlign: 'center',
|
||||
marginHorizontal: 15,
|
||||
}}>
|
||||
Example: Upload ImagePicker result
|
||||
</Text>
|
||||
)}
|
||||
|
||||
<Button
|
||||
onPress={this._pickImage}
|
||||
title="Pick an image from camera roll"
|
||||
/>
|
||||
|
||||
<Button onPress={this._takePhoto} title="Take a photo" />
|
||||
|
||||
{this._maybeRenderImage()}
|
||||
{this._maybeRenderUploadingOverlay()}
|
||||
|
||||
<StatusBar barStyle="default" />
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
_maybeRenderUploadingOverlay = () => {
|
||||
if (this.state.uploading) {
|
||||
return (
|
||||
<View
|
||||
style={[
|
||||
StyleSheet.absoluteFill,
|
||||
{
|
||||
backgroundColor: 'rgba(0,0,0,0.4)',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
]}>
|
||||
<ActivityIndicator color="#fff" animating size="large" />
|
||||
</View>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
_maybeRenderImage = () => {
|
||||
let { image } = this.state;
|
||||
if (!image) {
|
||||
return;
|
||||
}
|
||||
|
||||
return (
|
||||
<View
|
||||
style={{
|
||||
marginTop: 30,
|
||||
width: 250,
|
||||
borderRadius: 3,
|
||||
elevation: 2,
|
||||
}}>
|
||||
<View
|
||||
style={{
|
||||
borderTopRightRadius: 3,
|
||||
borderTopLeftRadius: 3,
|
||||
shadowColor: 'rgba(0,0,0,1)',
|
||||
shadowOpacity: 0.2,
|
||||
shadowOffset: { width: 4, height: 4 },
|
||||
shadowRadius: 5,
|
||||
overflow: 'hidden',
|
||||
}}>
|
||||
<Image source={{ uri: image }} style={{ width: 250, height: 250 }} />
|
||||
</View>
|
||||
<Text
|
||||
onPress={this._copyToClipboard}
|
||||
onLongPress={this._share}
|
||||
style={{ paddingVertical: 10, paddingHorizontal: 10 }}>
|
||||
{image}
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
_share = () => {
|
||||
Share.share({
|
||||
message: this.state.image,
|
||||
title: 'Check out this photo',
|
||||
url: this.state.image,
|
||||
});
|
||||
};
|
||||
|
||||
_copyToClipboard = () => {
|
||||
Clipboard.setString(this.state.image);
|
||||
alert('Copied image URL to clipboard');
|
||||
};
|
||||
|
||||
_takePhoto = async () => {
|
||||
let pickerResult = await ImagePicker.launchCameraAsync({
|
||||
allowsEditing: true,
|
||||
aspect: [4, 3],
|
||||
});
|
||||
|
||||
this._handleImagePicked(pickerResult);
|
||||
};
|
||||
|
||||
_pickImage = async () => {
|
||||
let pickerResult = await ImagePicker.launchImageLibraryAsync({
|
||||
allowsEditing: true,
|
||||
aspect: [4, 3],
|
||||
});
|
||||
|
||||
this._handleImagePicked(pickerResult);
|
||||
};
|
||||
|
||||
_handleImagePicked = async pickerResult => {
|
||||
try {
|
||||
this.setState({ uploading: true });
|
||||
|
||||
if (!pickerResult.cancelled) {
|
||||
uploadUrl = await uploadImageAsync(pickerResult.uri);
|
||||
this.setState({ image: uploadUrl });
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
alert('Upload failed, sorry :(');
|
||||
} finally {
|
||||
this.setState({ uploading: false });
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
async function uploadImageAsync(uri) {
|
||||
// Why are we using XMLHttpRequest? See:
|
||||
// https://github.com/expo/expo/issues/2402#issuecomment-443726662
|
||||
const blob = await new Promise((resolve, reject) => {
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.onload = function() {
|
||||
resolve(xhr.response);
|
||||
};
|
||||
xhr.onerror = function(e) {
|
||||
console.log(e);
|
||||
reject(new TypeError('Network request failed'));
|
||||
};
|
||||
xhr.responseType = 'blob';
|
||||
xhr.open('GET', uri, true);
|
||||
xhr.send(null);
|
||||
});
|
||||
|
||||
const ref = firebase
|
||||
.storage()
|
||||
.ref()
|
||||
.child(uuid.v4());
|
||||
const snapshot = await ref.put(blob);
|
||||
|
||||
// We're done with the blob, close and release it
|
||||
blob.close();
|
||||
|
||||
return await snapshot.ref.getDownloadURL();
|
||||
}
|
||||
22
with-firebase-storage-upload/README.md
Normal file
22
with-firebase-storage-upload/README.md
Normal file
@@ -0,0 +1,22 @@
|
||||
# Firebase Storage Upload Example
|
||||
|
||||
<p>
|
||||
<!-- iOS -->
|
||||
<img alt="Supports Expo iOS" longdesc="Supports Expo iOS" src="https://img.shields.io/badge/iOS-4630EB.svg?style=flat-square&logo=APPLE&labelColor=999999&logoColor=fff" />
|
||||
<!-- Android -->
|
||||
<img alt="Supports Expo Android" longdesc="Supports Expo Android" src="https://img.shields.io/badge/Android-4630EB.svg?style=flat-square&logo=ANDROID&labelColor=A4C639&logoColor=fff" />
|
||||
</p>
|
||||
|
||||
This example demonstrates how you can upload images (and other files) to Firebase Storage. Read App.js for more info, in particular the `uploadImageAsync` function.
|
||||
|
||||
## 🚀 How to use
|
||||
|
||||
- Run `yarn` or `npm install`
|
||||
- Run [`expo start`](https://docs.expo.io/versions/latest/workflow/expo-cli/), try it out.
|
||||
- Take a new picture or upload one from your library
|
||||
- See the image being rendered from Firebase
|
||||
|
||||
## 📝 Notes
|
||||
|
||||
- [Firebase Storage API](https://firebase.google.com/docs/storage/web/upload-files)
|
||||
- [Expo Firebase guide](https://docs.expo.io/versions/latest/guides/using-firebase/)
|
||||
12
with-firebase-storage-upload/app.json
Normal file
12
with-firebase-storage-upload/app.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"expo": {
|
||||
"name": "with-firebase-storage-upload",
|
||||
"version": "1.0.0",
|
||||
"icon": "https://github.com/expo/expo/blob/master/templates/expo-template-blank/assets/icon.png?raw=true",
|
||||
"splash": {
|
||||
"image": "https://github.com/expo/expo/blob/master/templates/expo-template-blank/assets/splash.png?raw=true",
|
||||
"resizeMode": "contain",
|
||||
"backgroundColor": "#ffffff"
|
||||
}
|
||||
}
|
||||
}
|
||||
6
with-firebase-storage-upload/babel.config.js
Normal file
6
with-firebase-storage-upload/babel.config.js
Normal file
@@ -0,0 +1,6 @@
|
||||
module.exports = function(api) {
|
||||
api.cache(true);
|
||||
return {
|
||||
presets: ['babel-preset-expo'],
|
||||
};
|
||||
};
|
||||
16
with-firebase-storage-upload/package.json
Normal file
16
with-firebase-storage-upload/package.json
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"expo": "^36.0.0",
|
||||
"expo-image-picker": "8.0.2",
|
||||
"expo-permissions": "8.0.0",
|
||||
"firebase": "7.8.1",
|
||||
"react": "16.9.0",
|
||||
"react-dom": "16.9.0",
|
||||
"react-native": "https://github.com/expo/react-native/archive/sdk-36.0.0.tar.gz",
|
||||
"uuid": "3.4.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "7.0.0",
|
||||
"babel-preset-expo": "8.0.0"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user