Существуют различные способы достижения этого.Я собираюсь выделить самый простой способ для вас сделать это.Я предполагаю, что у вас есть сервис хранения, такой как Amazon S3, где вы храните фотографию.Самый простой способ - сначала загрузить изображение на свой S3, в теле ответа будет указан URL-адрес загруженной фотографии.Затем вы можете взять этот URL вместе со своими значениями формы и передать их в бэкэнд.
//Example.js
import React, { Component } from 'react';
import {
//Whatever RN Components you need
StyleSheet,
Text,
View,
Alert,
TouchableHighlight,
TextInput,
ActivityIndicator,
ScrollView,
Picker,
Linking,
Image,
} from 'react-native';
import axios from 'axios';
import { RNS3 } from 'react-native-aws3';
import ImagePicker from 'react-native-image-picker';
export default class RegisterScreen extends Component {
state = {
email: '',
password: '',
confirmedPassword: '',
firstName: '',
lastName: '',
avatar: '',
avatarUri: '',
avatarName: '',
avatarType: '',
loading: false,
errorMessage: '',
uploadMessage: ''
}
onRegisterPress = () => {
this.setState({
errorMessage: '',
registerLoading: true,
uploadMessage: 'This may take a while: Uploading your Profile Pic...'
});
const avatarFile = {
uri: this.state.avatarUri,
name: this.state.avatarName,
type: this.state.avatarType
};
const avatarOptions = {
keyPrefix: 'uploads/path/avatar/' + this.state.email + '/' + new Date().getTime(),
bucket: 'your-bucket-s3',
region: 'us-west-2',
accessKey: 'ACCESSKEY',
secretKey: 'SECRETKEY',
successActionStatus: 201
};
RNS3.put(avatarFile, avatarOptions)
.then((response) => {
if (response.status === 201) {
this.setState({ avatar: response.body.postResponse.location });
} else {//handle error}
})
.then(() => {
this.setState({
uploadMessage: 'Creating your profile'
});
const url = 'someremoteurl.com';
const payload = {
email: this.state.email,
password: this.state.password,
password_confirmation: this.state.confirmedPassword,
first_name: this.state.firstName,
last_name: this.state.lastName,
avatar: this.state.avatar,
};
axios.post(url, payload)
.then((r) => {
this.setState({
uploadMessage: '',
loading: false
});
if (r.status === 200) {
//handle success
}
})
.catch(() => {
// handle form submission error
this.setState({
uploadMessage: '',
loading: false,
error: true
});
});
});
}
openMediaLibrary() {
const options = {
title: 'Select Photo',
storageOptions: {
skipBackup: true,
path: 'images'
}
};
ImagePicker.showImagePicker(options, (response) => {
console.log('Response = ', response);
if (response.didCancel) {
console.log('Cancelled selection of image');
} else if (response.error) {
console.log('Image Picker error', response.error)
} else {
this.setState({
avatarUri: response.uri,
avatarName: response.fileName,
avatarType: response.type
});
}
});
}
render() {
return (
<ScrollView style={{ margin: 15 }}>
<View style={styles.formField}>
<Text style={styles.formLabelStyle}> Email</Text>
<TextInput
placeholder='john@yahoo.com'
underlineColorAndroid='transparent'
onChangeText={(email) => this.setState({ email })}
value={this.state.email}
autoCapitalize='none'
/>
</View>
<View style={styles.formField}>
<Text style={styles.formLabelStyle}> Password (minimum of 8 letters)</Text>
<TextInput
placeholder='password'
underlineColorAndroid='transparent'
onChangeText={(password) => this.setState({ password })}
value={this.state.password}
secureTextEntry
autoCorrect={false}
autoCapitalize='none'
/>
</View>
<View style={styles.formField}>
<Text style={styles.formLabelStyle}> Password Confirmation</Text>
<TextInput
placeholder='retype your password'
underlineColorAndroid='transparent'
onChangeText={(confirmedPassword) => this.setState({ confirmedPassword })}
value={this.state.confirmedPassword}
secureTextEntry
autoCorrect={false}
autoCapitalize='none'
/>
</View>
<View style={styles.formField}>
<Text style={styles.formLabelStyle}> First Name</Text>
<TextInput
placeholder='First Name'
underlineColorAndroid='transparent'
onChangeText={(firstName) => this.setState({ firstName })}
value={this.state.firstName}
/>
</View>
<View style={styles.formField}>
<Text style={styles.formLabelStyle}>Last Name</Text>
<TextInput
placeholder='Last Name'
underlineColorAndroid='transparent'
onChangeText={(lastName) => this.setState({ lastName })}
value={this.state.lastName}
/>
</View>
<View>
<View style={{ padding: 10 }}>
{
this.state.avatarUri.length > 0 ?
<Image
source={{ uri: this.state.avatarUri }}
style={{ width: 140, height: 140 }}
/>
: null
}
</View>
<Button
small
backgroundColor='#13CE66'
title={(this.state.avatarUri.length === 0) ?
'Choose Profile Picture' : 'Change Profile Picture'}
onPress={() => this.openMediaLibrary()}
/>
</View>
<Button
large
backgroundColor='#13CE66'
title='Submit'
onPress={() => this.onRegisterPress() }
/>
</ScrollView>
)
}
}
Поэтому, когда вы пытаетесь зарегистрировать этого пользователя, изображение сначала загружается, а полученный URL сохраняется в состоянии, чтобыиспользоваться как часть параметров формы для аватара.Это легко, недостатком является необходимость ждать ответа загрузки перед тем, как отправлять параметры формы
РЕДАКТИРОВАТЬ
Если вы не используете стороннюю службу хранения или предпочитаете отправлятьфайл на ваши собственные серверы, затем используйте FormData()
:
//OnRegisterPress function should look like this:
onRegisterPress = () => {
let form = new FormData();
form.append('avatar', {
//from openMedia Function, image selected with image-picker
uri: this.state.avatarUri,
name: this.state.avatarName,
type: this.state.avatarType
});
// append your other params such as email, password, name
form.append('email', this.state.email)
form.append('password', this.state.password)
// when you are done appending, use fetch to send the form data as axios seems to be having a bit of issues doing this.
fetch('http://yourapiendpoint', {
headers: {
'Accept': 'application/json',
'Content-Type': 'multipart/form-data'
},
method: 'POST',
body: form
});
}