如何使用API 将照片与表单数据一起上传到后端服务器?

问题描述 投票:1回答:1

下面是我的代码,我正在尝试捕获图像并填充其他输入字段。一旦我点击“创建”按钮,我就会调用api将其上传到后端服务器。但是如何将文件详细信息发送到后端?我有邮递员的工作api。有些字段我没有在这里包含一些输入字段代码,因为这里的代码很大。

API在邮递员中使用以下字段

enter image description here

   import React, {Component} from 'react';
    import {
        StyleSheet,
        Button,
        TextInput,
        Text,
        TouchableOpacity,
        View,
        Picker,
        Image,
    } from 'react-native';
    import ImagePicker from 'react-native-image-picker';

    export default class CreateStudent extends React.Component {
        constructor(props){
            super(props);
            this.state = {
                studentName: '',
                email: '',
                newPassword: '',
                fileShow: '',
                faceDetails: '',
                school: 1,
            }
        }

        handleEmail = (text) => {
            this.setState({ email: text })
        }

        handlePassword = (text) => {
            this.setState({ newPassword: text })
        }

        handleName = (text) => {
            this.setState({ studentName: text })
        }

        selectImage = () => {
            const options = {
                quality: 1.0,
                maxWidth: 75,
                maxHeight: 75
            }
            ImagePicker.launchCamera(options,(responce)=>{
                const fileDetails ={
                    uri : responce.uri,
                    name :responce.fileName,
                    method: 'POST',
                    width : 50,
                    height : 50,
                    path : responce.path,
                    type :  responce.type,
                  }
                 this.setState({
                    fileShow: responce.uri,
                    faceDetails: fileDetails
                 })
                console.log(this.state.fileShow);
                console.log(fileDetails);
            })
        }

        async onCreateStudentPressed() {
            try {
                let response = await fetch('http://10.0.2.2:5000/api/students/create', {
                    method: 'POST',
                    headers: {
                       'Accept': 'application/json',
                       'Content-Type': 'application/json',
                    },
                    body: JSON.stringify({
                         file: this.state.fileDetails,
                         email: this.state.email,
                         password: this.state.newPassword,
                         phone_number: this.state.phoneNumber,
                         class: this.state.class,
                         section: this.state.section,
                         school: this.state.school,
                         name: this.state.studentName
                    })
                });
                let res = await response.text();
                if (response.status >= 200 && response.status < 300) {
                     //Handle success
                     let accessToken = res;
                     console.log(accessToken);
                     //On success we will store the access_token in the AsyncStorage
                     //this.storeToken(accessToken);
                } else {
                     //Handle error
                     let error = res;
                     throw error;
                }
            } catch(error) {
                this.setState({error: error});
                console.log("error " + error);
                this.setState({
                   passwordUpdated: false
                })
            }
         }

        render() {
            return (
                <View>
                    <View style={styles.formContainer}>
                        <Text style ={styles.pageTitle} >Create Student</Text>
                        <View style={styles.Camera}>
                            <TouchableOpacity onPress={this.selectImage}>
                              <Text>Take Picture</Text>
                            </TouchableOpacity>
                        </View>
                        {
                            this.state.fileShow !== '' ?
                            <View style={styles.showBlack}>
                                <View style={styles.placeholder}>
                                    <Image key={1} source={{uri: this.state.fileShow}} style={styles.previewImage} />
                                </View>
                            </View>
                            :
                            null
                        }
                        <TextInput
                            placeholder='Enter Student Name'
                            placeholderTextColor='#808080'
                            style ={styles.textInput}
                            underlineColorAndroid={'transparent'}
                            onChangeText = {this.handleName}
                        />
                        <TextInput
                            placeholder='Enter Student Email'
                            placeholderTextColor='#808080'
                            style ={styles.textInput}
                            underlineColorAndroid={'transparent'}
                            onChangeText = {this.handleEmail}
                        />
                        <TextInput
                            placeholder='Enter Password'
                            placeholderTextColor='#808080'
                            secureTextEntry={true}
                            style ={styles.textInput}
                            underlineColorAndroid={'transparent'}
                            onChangeText = {this.handlePassword}
                        />
                        <Button
                            onPress={this.onCreateStudentPressed.bind(this)}
                            style ={styles.loginBtn}
                            title="Create"
                        />
                    </View>  
                </View>
            );
        }
    }
api react-native image-uploading
1个回答
0
投票

有多种方法可以实现这一目标。我将重点介绍最简单的方法。我假设您有一个存储服务,例如存储照片的Amazon S3。最简单的方法是首先将图像上传到S3,响应正文将包含上传照片的网址。然后,您可以将该网址与您的表单值一起使用,并将它们传递给您的后端。

//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='[email protected]'
                            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
   });
}
© www.soinside.com 2019 - 2024. All rights reserved.