I am trying to upload images from my phone which is perfectly working in iOS but it failed to work in android, have tried several android devices and all could not upload image to server. Have tried all various methods that I could find in web but none is working, wondering is it a problem with my code, expo, RN or android?
React native 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> ); }}@connectActionSheetclass 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> ); }}
Backend 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;}
When I console.log my FormData in react native, the result are as follows:
/* 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 FormDataFormData {"_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", }, ], ],}
When I tried to console.log $_FILES['photo']['tmp_name'] after uploading with iOS, it does return a value "C:/xampp/tmp/file", but when trying to console.log the file after uploading with android, it does not return any value.
Thank you all in advance