从Android反应Native Expo上传图像不起作用

时间:2019-06-17 10:40:23

标签: javascript android react-native react-native-android expo

我正在尝试从我的手机上载图片,该手机在iOS上运行正常,但在android上无法正常工作,尝试了多个android设备,但都无法将图片上传到服务器。已经尝试了我可以在Web上找到的所有各种方法,但是都没有用,想知道我的代码,expo,RN或android是否有问题?

反应本机Upload.js

import React from 'react';
import {
    ActionSheetIOS,
    Text,
    View,
    Platform,
    Image,
    TouchableOpacity
} from 'react-native';
import { ImagePicker } from 'expo';
import { ActionSheetProvider, connectActionSheet } from '@expo/react-native-action-sheet';

export default class TestUpload extends React.Component {
    render() {
        return(
            <ActionSheetProvider>
                <TestUploadApp />
            </ActionSheetProvider>
        );
    }
}

@connectActionSheet
class TestUploadApp extends React.Component {
    constructor(props) {
        super(props)
        this.state = {
            imageSource: null,
            imageUri: '',
            imageName: '',
            imageType: ''
        }
    }

    async getPermissionAsync() {
        const { CAMERA_ROLL, Permissions } = Expo;
        try {
            const status = await Permissions.askAsync(Permissions.CAMERA_ROLL);
            return(status);
        } catch(e) {
            console.log(e);
        }

        if (status === 'granted') {
            return CAMERA_ROLL.getCurrentPositionAsync({enableHighAccuracy: true});
        } else {
            throw new Error('Camera Roll permission not granted');
        }
    }

    async getPermissionCamera() {
        const { CAMERA, Permissions } = Expo;
        try {
            const status = await Permissions.askAsync(Permissions.CAMERA);
            return(status);
        } catch(e) {
            console.log(e);
        }

        if (status === 'granted') {
            return CAMERA.getCurrentPositionAsync({enableHighAccuracy: true});
        } else {
            throw new Error('Camera permission not granted');
        }
    }

    componentDidMount() {
        this.getPermissionAsync();
        this.getPermissionCamera();
    }

    _PickImage = async() => {
        let result = await ImagePicker.launchImageLibraryAsync({
            allowsEditing: true,
            aspect: [4, 4]
        });
        console.log(result);

        if(!result.cancelled) {
            let localUri = result.uri;
            let filename = localUri.split('/').pop();

            // Infer the type of the image
            let match = /\.(\w+)$/.exec(filename);
            let type = match ? `image/${match[1]}` : `image`;

            let source = { uri: result.uri };
            this.setState({ 
                imageSource: source,
                imageUri: localUri,
                imageName: filename,
                imageType: type
            });
        }
    }

    _PickCamera = async() => {
        let result = await ImagePicker.launchCameraAsync({
            allowsEditing: true,
            aspect: [4, 4]
        });
        console.log(result);

        if(!result.cancelled) {
            let localUri = result.uri;
            let filename = localUri.split('/').pop();

            // Infer the type of the image
            let match = /\.(\w+)$/.exec(filename);
            let type = match ? `image/${match[1]}` : `image`;

            let source = { uri: result.uri };
            this.setState({ 
                imageSource: source,
                imageUri: localUri,
                imageName: filename,
                imageType: type
            });
        }
    }

    _ShowActionSheet = () => {
        if(Platform.OS === 'ios') {
            ActionSheetIOS.showActionSheetWithOptions({
                options: ['Cancel', 'Take Photo', 'Choose From Gallery'],
                cancelButtonIndex: 0,
            },
            (buttonIndex) => {
                if(buttonIndex === 1) {
                    this._PickCamera();
                } else if (buttonIndex === 2) { 
                    this._PickImage();
                }
            });
        } else if(Platform.OS === 'android') {
            let options = ['Choose From Gallery', 'Take Photo', 'Cancel'];
            let cancelButtonIndex = 2;

            this.props.showActionSheetWithOptions({
                options,
                cancelButtonIndex,
            },
            (buttonIndex) => {
                if(buttonIndex === 0) {
                    this._PickImage();
                } else if (buttonIndex === 1) { 
                    this._PickCamera();
                }
            });
        }
    }

    SignUpProfile = () => {
        const { imageUri, imageName, imageType } = this.state;

        if(imageUri != null && imageUri != '') {
            // Upload Image
            let formData = new FormData();
            formData.append('photo', {
                uri: imageUri,
                type: imageType,
                name: imageName,
            });
            console.log(formData);
            fetch(`${global.api}data_controller/signup_profile_upload_photo`, {
                method: 'POST',
                body: formData,
                header: {
                    'Content-Type': 'multipart/form-data'
                }
            }).then((response) => response.json())
            .then((responseJson) => {
                console.log(responseJson);
            }).catch((error) => {
                console.error(error);
            });
        }
    }

    render() {
        return(
            <View>
                <TouchableOpacity
                    onPress={this._ShowActionSheet}
                >
                    <Image 
                        style={{
                            width: 100,
                            height: 100,
                        }}
                        source={this.state.imageSource != null ? this.state.imageSource : require('../../assets/images/tempat_ibadah.jpg')}
                    />
                </TouchableOpacity>

                <TouchableOpacity
                    onPress={ this.SignUpProfile }
                >
                    <Text>Upload</Text>
                </TouchableOpacity>
            </View>
        );
    }
}

后端PHP upload-photo.php

/* I am using CodeIgniter 3.1.5
 * In this case I have tried several methods
 */

public function signup_profile_upload_photo() {
    /* Method 1 using CI upload library */
    /* Failed to upload in iOS and android */

    $dir = './tmp';

    if(!is_dir($dir)) {
        if(mkdir($dir, 0777, TRUE)) {
            $index = '<!DOCTYPE HTML><html><head><title>403 Forbidden</title></head><body><p>Directory access is forbidden.</p></body></html>';
            write_file($dir . "/index.html", $index);
        }
    }

    $config['upload_path'] = $dir;
    $config['allowed_types'] = 'gif|jpg|png';
    $this->load->library('upload', $config);

    if($this->upload->do_upload('photo')) {
        $callback['success'] = '1';
    } else {
        $callback['success'] = '0';
    }

    /* End of Method 1 */

    /* Method 2, work perfectly in iOS, but not working in all android devices */

    if(move_uploaded_file($_FILES['photo']['tmp_name'], './tmp/photo.jpg')) {
        $callback['move'] = '1';
    } else {
        $callback['move'] = '0';
    }

    $data = json_encode($callback);
    echo $data;

}

当我用react native控制台登录我的FormData时,结果如下:

/* Android */
/* When selecting image */

Object {
  "cancelled": false,
  "height": 3120,
  "type": "image",
  "uri": "file:///data/user/0/host.exp.exponent/cache/ExperienceData/%2540username%252Fprojectname/ImagePicker/538f376d-9a8c-4c4b-bc7f-bf3796785cec.jpg",
  "width": 3120,
}

/* After appending to FormData
FormData {
  "_parts": Array [
    Array [
      "photo",
      Object {
        "name": "538f376d-9a8c-4c4b-bc7f-bf3796785cec.jpg",
        "type": "image/jpg",
        "uri": "file:///data/user/0/host.exp.exponent/cache/ExperienceData/%2540username%252Fprojectname/ImagePicker/538f376d-9a8c-4c4b-bc7f-bf3796785cec.jpg",
      },
    ],
  ],
}

/* iOS */
/* Selecting image */

Object {
  "cancelled": false,
  "height": 1125,
  "type": "image",
  "uri": "file:///var/mobile/Containers/Data/Application/200DE4DB-AD0D-40A2-9BF6-4C25B147B5B1/Library/Caches/ExponentExperienceData/%2540username%252Fprojectname/ImagePicker/1772B1F0-32EF-4212-8D56-374AD57535B9.png",
  "width": 1122,
}

/* FormData */
FormData {
  "_parts": Array [
    Array [
      "photo",
      Object {
        "name": "1772B1F0-32EF-4212-8D56-374AD57535B9.png",
        "type": "image/png",
        "uri": "file:///var/mobile/Containers/Data/Application/200DE4DB-AD0D-40A2-9BF6-4C25B147B5B1/Library/Caches/ExponentExperienceData/%2540username%252Fprojectname/ImagePicker/1772B1F0-32EF-4212-8D56-374AD57535B9.png",
      },
    ],
  ],
}

在使用iOS上传后,当我尝试console.log $ _FILES ['photo'] ['tmp_name']时,它的确返回值“ C:/ xampp / tmp / file”,但在尝试console.log时用android上传后的文件,它不返回任何值。

谢谢大家

0 个答案:

没有答案