I am trying to make a upload function for my Firebase Cloud Storage. I am using RNFetchBlob, along with react-native-image-picker. I can select photos, but it will not upload. All other Firebase functions works great and it is installed through React-Native-Firebase...
Nothing seems to happen after 'fs.readFile'.
import React, { Component } from 'react'
import {
StyleSheet,
Text,
View,
TouchableOpacity,
Platform,
Image,
ActivityIndicator
} from 'react-native'
import ImagePicker from 'react-native-image-picker'
import RNFetchBlob from 'rn-fetch-blob'
import firebase from 'react-native-firebase';
const storage = firebase.storage()
// Prepare Blob support
const Blob = RNFetchBlob.polyfill.Blob
const fs = RNFetchBlob.fs
window.XMLHttpRequest = RNFetchBlob.polyfill.XMLHttpRequest
window.Blob = Blob
const uploadImage = (uri, mime = 'application/octet-stream') => {
return new Promise((resolve, reject) => {
const uploadUri = Platform.OS === 'ios' ? uri.replace('file://', '') : uri
const sessionId = new Date().getTime()
let uploadBlob = null
const imageRef = storage.ref('images').child('${sessionId}')
fs.readFile(uploadUri, 'base64')
.then((data) => {
return Blob.build(data, { type: '${mime};BASE64' })
})
.then((blob) => {
uploadBlob = blob
return imageRef.put(blob, { contentType: mime })
})
.then(() => {
uploadBlob.close()
return imageRef.getDownloadURL()
})
.then((url) => {
resolve(url)
})
.catch((error) => {
reject(error)
})
})
}
class Demo extends Component {
constructor(props) {
super(props)
this.state = {}
}
_pickImage() {
this.setState({ uploadURL: '' })
ImagePicker.launchImageLibrary({}, response => {
uploadImage(response.uri)
.then(url => this.setState({ uploadURL: url }))
.catch(error => console.log(error))
})
}
render() {
return (
<View style={ styles.container }>
{
(() => {
switch (this.state.uploadURL) {
case null:
return null
case '':
return <ActivityIndicator />
default:
return (
<View>
<Image
source={{ uri: this.state.uploadURL }}
style={ styles.image }
/>
<Text>{ this.state.uploadURL } {this.state.uploadURL}</Text>
</View>
)
}
})()
}
<TouchableOpacity onPress={ () => this._pickImage() }>
<Text style={ styles.upload }>
Upload
</Text>
</TouchableOpacity>
</View>
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
image: {
height: 200,
resizeMode: 'contain',
},
upload: {
textAlign: 'center',
color: '#333333',
padding: 10,
marginBottom: 5,
borderWidth: 1,
borderColor: 'gray'
},
})
export default Demo
I get this error in my console when selecting a photo:
filePath.replace is not a function. (In 'filePath.replace('file://', '')', 'filePath.replace' is undefined)]
Just pass the image url directly to storage ref. You don't need to create a blob file anymore. I guess firebase handles it internally now.
Here an example i just tested together with react-native-image-crop-picker:
import firebase from 'react-native-firebase';
import ImagePicker from 'react-native-image-crop-picker';
export default class ImageUploadService {
static init() {}
static openPickerAndUploadImage() {
const uid = '12345';
ImagePicker.openPicker({
width: 300,
height: 300,
cropping: true,
mediaType: 'photo',
})
.then(image => {
const imagePath = image.path;
const imageRef = firebase
.storage()
.ref(uid)
.child('dp.jpg');
let mime = 'image/jpg';
imageRef
.put(imagePath, { contentType: mime })
.then(() => {
return imageRef.getDownloadURL();
})
.then(url => {
// You could now update your users avatar for example
//firebase.database().ref('users').child(uid).update({ ...userData})
console.log('URL', url);
});
})
.catch(error => {
console.log(error);
});
}
}
ImageUploadService.init();
Now just call ImageUploadService.openopenPickerAndUploadImage() in one of your components.
I am sure this will also work with react-native-image-picker too, just remove the blob parts in your code and pass the image url directly to your imageRef.put
==>
const uploadImage = (uri, mime = 'application/octet-stream') => {
return new Promise((resolve, reject) => {
const imagePath = uri;
const imageRef = firebase
.storage()
.ref('images')
.child('dp.jpg');
let mime = 'image/jpg';
imageRef
.put(imagePath, { contentType: mime })
.then(() => {
return imageRef.getDownloadURL();
})
.then(resolve)
.catch(reject);
});
};