我正在尝试从我的手机上载图片,该手机在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上传后的文件,它不返回任何值。
谢谢大家