使用 React Native 将图像上传到 Firebase
Posted
技术标签:
【中文标题】使用 React Native 将图像上传到 Firebase【英文标题】:Upload an image to Firebase with React Native 【发布时间】:2020-06-21 14:46:25 【问题描述】:我正在尝试将照片上传器制作到 firebase 以响应本机。我遵循了一个教程并采用了一对一的代码。但是,在我想执行代码之后,一切似乎都可以正常工作,直到必须上传代码,然后我收到以下错误:
可能的未处理承诺拒绝(id:0):错误:未知错误 已经发生了。 fn@http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:2132:45 http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:127402:44 putFile@http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:137147:104 上传图片@http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:210966:91 touchableHandlePress@http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:54240:47 touchableHandlePress@[本机代码] _performSideEffectsForTransition@http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:52872:36 _performSideEffectsForTransition@[本机代码] _receiveSignal@http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:52798:46 _receiveSignal@[native code] touchableHandleResponderRelease@http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:52677:26 touchableHandleResponderRelease@[本机代码] invokeGuardedCallbackImpl@http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:8997:21 调用GuardedCallback@http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:9093:42 invokeGuardedCallbackAndCatchFirstError@http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:9097:36 执行调度@http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:9204:48 执行DispatchesInOrder@http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:9224:26 执行DispatchesAndRelease@http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:9329:35 forEach@[本机代码] forEachAccumulated@http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:9319:22 runEventsInBatch@http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:9353:27 runExtractedPluginEventsInBatch@http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:9441:25 http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:10467:42 批量更新$1@http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:21921:20 批量更新@http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:10415:36 _receiveRootNodeIDEvent@http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:10466:23 接收触摸@http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:10496:34 __callFunction@http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:2650:49 http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:2363:31 __guard@http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:2604:15 callFunctionReturnFlushedQueue@http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:2362:21 callFunctionReturnFlushedQueue@[本机代码]
有人熟悉将图片上传到 Firebase 吗?在本教程中,他们使用 uuid,但由于某种原因,当我尝试使用它时应用程序会中断,所以我将其省略了。这是对应的代码:
import React, Component from 'react';
import Platform, StyleSheet, Text, View, Image, Button, ScrollView, ImageBackground, Dimensions,TouchableOpacity, FlatList,
AsyncStorage from 'react-native';
import Avatar, ListItem from 'react-native-elements';
import Icon from 'react-native-vector-icons/FontAwesome';
import ImagePicker from 'react-native-image-picker';
import firebase from 'react-native-firebase';
const SCREEN_WIDTH = Dimensions.get("window").width;
const list = [
title: '',
icon: 'cake',
url: 'ProfileSettings',
,
]
const options =
title: 'Select Image',
storageOptions:
skipBackup: true,
path: 'images'
;
const ImageRow = ( image, windowWidth, popImage ) => (
<View>
<Image
source= uri: image
style=[styles.img, width: windowWidth / 2 - 15 ]
onError=popImage
/>
</View>
);
class profileScreen extends Component
constructor(props)
super(props);
this.state =
first: '',
place: '',
province: '',
uid: '',
profileImg: '',
email: '',
imgSource: '',
uploading: false,
progress: 0,
images: []
getUserData = (user) =>
console.log(user);
let ref = firebase.database().ref('Users/' + user);
ref.on('value' , snapshot =>
var state = snapshot.val();
this.setState(
first: state.firstname,
place: state.place,
province: state.province,
uid: user,
profileImg: state.profileImg,
birthday: state.birthday,
email: state.email,
year: state.registered.split("-",1)
)
)
componentDidMount()
let user = firebase.auth().currentUser;
console.log(user);
console.log('test');
this.getUserData(user.uid);
let images;
AsyncStorage.getItem('images')
.then(data =>
images = JSON.parse(data) || [];
this.setState(
images: images
);
)
.catch(error =>
console.log(error);
);
/**
* Select image method
*/
pickImage = () =>
ImagePicker.showImagePicker(options, response =>
if (response.didCancel)
console.log('You cancelled image picker ????');
else if (response.error)
alert('And error occured: ', response.error);
else
const source = uri: response.uri ;
this.setState(
imgSource: source,
imageUri: response.uri
);
console.log(source);
);
;
/**
* Upload image method
*/
uploadImage = () =>
const ext = this.state.imageUri.split('.').pop(); // Extract image extension
const filename = `unique image' + $ext`; // Generate unique name
const imageRef = firebase.storage().ref('tutorials/images').child(filename +ext);
let mime = 'image/jpg';
imageRef.put(this.state.imageUri, contentType: mime ).then((snapshot)=>
console.log('Image uploaded successfully.')
).catch((error)=>
console.log('Image uploading failed:' + error);
);
;
/**
* Remove image from the state and persistance storage
*/
removeImage = imageIndex =>
let images = this.state.images;
images.pop(imageIndex);
this.setState( images );
AsyncStorage.setItem('images', JSON.stringify(images));
;
render()
const uploading, imgSource, progress, images = this.state;
const windowWidth = Dimensions.get('window').width;
const disabledStyle = uploading ? styles.disabledBtn : ;
const actionBtnStyles = [styles.btn, disabledStyle];
return (
<ScrollView style=styles.scorllVert>
<View style= alignItems: 'flex-start', justifyContent: 'center', marginBottom: 40 >
<View style=styles.intro>
<Text style=styles.introText>Hoi, ik ben this.state.first"\n"<Text style=styles.introTextSpan>Lid geworden in this.state.year</Text></Text>
this.state.profileImg ?
<Avatar size="large" rounded source=uri: this.state.profileImg, onPress=() => console.log("Works!") activeOpacity=0.7 />
:
<Avatar size="large" rounded title="GLR" onPress=() => console.log("Works!") activeOpacity=0.7 />
</View>
<View style=styles.divider>
</View>
<View style=styles.about>
<Text style=styles.profileName>Over</Text>
<View style=styles.aboutLiving>
<Icon name='home' style=styles.icon/>
<Text style=styles.aboutText>Woont in this.state.place, this.state.province</Text>
</View>
</View>
<View style=styles.divider>
</View>
<View style=styles.about>
<Text style=styles.profileName>Door this.state.first versterkt</Text>
<View style=styles.aboutLiving>
<Icon name='check-circle' style=[styles.icon, styles.iconGreen]/>
<Text style=styles.aboutText>E-mail adres</Text>
</View>
</View>
<View style=styles.divider>
</View>
<View style=styles.about>
<Text style=styles.profileName>Recente activiteiten</Text>
<Text >N.v.t.</Text>
<TouchableOpacity
style=actionBtnStyles
onPress=this.pickImage
disabled=uploading
>
<View>
<Text style=styles.btnTxt>Pick image</Text>
</View>
</TouchableOpacity>
imgSource !== '' && (
<View>
<Image source=imgSource style=styles.image />
uploading && (
<View
style=[styles.progressBar, width: `$progress%` ]
/>
)
<TouchableOpacity
style=actionBtnStyles
onPress=this.uploadImage
disabled=uploading
>
<View>
uploading ? (
<Text style=styles.btnTxt>Uploading ...</Text>
) : (
<Text style=styles.btnTxt>Upload image</Text>
)
</View>
</TouchableOpacity>
</View>
)
<View>
<Text
style=
fontWeight: '600',
paddingTop: 20,
alignSelf: 'center'
>
images.length > 0
? 'Your uploaded images'
: 'There is no image you uploaded'
</Text>
</View>
<FlatList
numColumns=2
style= marginTop: 20
data=images
renderItem=( item: image, index ) => (
<ImageRow
windowWidth=windowWidth
image=image
popImage=() => this.removeImage(index)
/>
)
keyExtractor=index => index
/>
</View>
</View>
</ScrollView>
);
const styles = StyleSheet.create(
profileName:
fontWeight: 'bold',
fontSize: 22,
marginTop: 20,
,
list:
marginTop: 40,
width: '100%'
,intro:
flex: 1,
flexDirection: 'row',
flexWrap: 'wrap',
alignItems: 'flex-start',
padding: 25,
marginBottom: 30,
paddingTop: 80,
,
introText:
marginLeft: 0,
marginRight: 50,
fontSize: 22,
fontWeight: "700",
marginTop:15,
,
introTextSpan:
marginLeft: 0,
marginRight: 40,
fontSize: 15,
fontWeight: "200",
marginTop:50,
,
divider:
width: SCREEN_WIDTH-50,
padding: 10,
borderBottomColor: 'grey',
borderBottomWidth: 0.5,
marginTop: 10,
marginLeft: 25
,
about:
paddingLeft: 25,
,
aboutLiving:
flexDirection: 'row',
flexWrap: 'wrap',
alignItems: 'flex-start',
paddingTop: 10
,
icon:
fontSize: 18
,
aboutText:
marginLeft: 30
,
iconGreen:
color: 'green'
,
button:
marginTop: 30,
marginBottom: 20,
paddingVertical: 10,
alignItems: 'center',
backgroundColor: '#019BB4',
width: 300
,
buttonText:
fontSize: 20,
fontWeight: 'bold',
color: '#fff'
,
scorllVert:
marginBottom: 40
,
btn:
paddingLeft: 20,
paddingRight: 20,
paddingTop: 10,
paddingBottom: 10,
borderRadius: 20,
backgroundColor: 'rgb(3, 154, 229)',
marginTop: 20,
alignItems: 'center'
,
disabledBtn:
backgroundColor: 'rgba(3,155,229,0.5)'
,
btnTxt:
color: '#fff'
,
image:
marginTop: 20,
minWidth: 200,
height: 200,
resizeMode: 'contain',
backgroundColor: '#ccc',
,
img:
flex: 1,
height: 100,
margin: 5,
resizeMode: 'contain',
borderWidth: 1,
borderColor: '#eee',
backgroundColor: '#ccc'
,
progressBar:
backgroundColor: 'rgb(3, 154, 229)',
height: 3,
shadowColor: '#000',
)
export default profileScreen;
我对本机反应还很陌生,想上传图片,有没有人可以帮助我完成这项工作?即使有其他方法,我也愿意接受!
【问题讨论】:
【参考方案1】:尝试将您的 uploadImage 函数包装在 try..catch 中,看看是否可以在 catch 中获得更清晰的错误消息
【讨论】:
【参考方案2】:试试这个代码上传图片,
const ext = this.state.imageUri.split('.').pop(); // Extract image extension
const filename = `unique image' + $ext`; // Generate unique name
const imageRef = firebase.storage().ref('tutorials/images).child(filename +ext);
let mime = 'image/jpg';
imageRef.put(this.state.imageUri, contentType: mime ).then((snapshot)=>
console.log('Image uploaded successfully.')
).catch((error)=>
console.log('Image uploading failed');
);
【讨论】:
感谢您的帮助,但只有 1 个问题,imageRef.put( 之后的 imageUrl 来自哪里? 是同一个状态变量(imageUri)。我正在更新代码。 我用你的函数更新了上面的代码,但遗憾的是它没有上传图片并以“图片上传失败:错误:发生未知错误”结束 那么请在 Firebase 控制台的Rules
标签(第二个标签)下的Storage
部分检查您的规则。如果您未通过身份验证,默认规则不允许您编写任何内容。如果您不希望任何身份验证来写入访问权限,那么您只需将该行修改为 allow read, write;
规则全部允许:rules_version = '2'; 2 service firebase.storage 3 match /b/bucket/o 4 match /allPaths=** 5 allow read, write; 6 7 8
以上是关于使用 React Native 将图像上传到 Firebase的主要内容,如果未能解决你的问题,请参考以下文章
如何将 React Native 应用程序上的本地图像文件上传到 Rails api?
将图像从 Firebase 存储链接到 Firestore 文档并在 React Native 中显示它们