React Native 图片上传

22

我在上传照片到我的相机胶卷或API时遇到了问题。这是我目前正在使用的代码。我能够从相机胶卷和相机中获取图像数据。但是我无法将数据发布到服务器上,不知道自己哪里出了问题。

import React, { Component } from 'react';
import {
  Text,
  View,
  PixelRatio,
  TouchableOpacity,
  Image,
  Platform,
  NativeModules,
  DeviceEventEmitter
} from 'react-native';
import { connect } from 'react-redux';
import ImagePicker from 'react-native-image-picker';
import { captureProflieAvitar } from '../../actions';

var RNUploader = NativeModules.RNUploader;
class NewCamera extends Component {
  state = {
    avatarSource: null,
    imgBase64: []
  }
  componentDidMount() {
    // upload progress
    DeviceEventEmitter.addListener('RNUploaderProgress', (data) => {
      const bytesWritten = data.totalBytesWritten;
      const bytesTotal = data.totalBytesExpectedToWrite;
      const progress = data.progress;
      console.log(bytesWritten, bytesTotal);
      console.log( "upload progress: " + progress + "%");
    });
}

  selectPhotoTapped() {
    const options = {
      quality: 0.75,
      maxWidth: 300,
      maxHeight: 300,
      storageOptions: {
      skipBackup: true
      }
    };
    ImagePicker.showImagePicker(options, (response) => {
      console.log('Response = ', response);

      if (response.didCancel) {
        console.log('User cancelled photo picker');
      } else if (response.error) {
        console.log('ImagePicker Error: ', response.error);
      } else if (response.customButton) {
        console.log('User tapped custom button: ', response.customButton);
      } else {
        let source;
        // You can display the image using either:
        source = { uri: 'data:image/jpeg;base64,' + response.data, isStatic: true };

        const temp = response.data;

        //Or:
        if (Platform.OS === 'android') {
          source = { uri: response.uri, isStatic: true };
        } else {
          source = { uri: response.uri.replace('file://', ''), isStatic: true };
        }

        this.setState({
          avatarSource: source,
          imgBase64: temp,
        });
      }
    });
  }

doUpload() {

    const files = {
            filepath: `data:image/png;base64,${this.state.imgBase64}`,
        };
    const opts = {
        url: 'https://central.tipflip.co?apior=MYAPIKEY&tfReqID3031&tfUserID=1&tfImage=',
        files,
        method: 'POST',
        headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    };

    RNUploader.upload(opts, (err, response) => {
        if (err) {
            console.log(err);
            return;
        }
        const status = response.status;
        const responseString = response.data;
        const json = JSON.parse(responseString);
        console.log('upload complete with status ' + status);
    });
}
  render() {
    return (
      <View style={styles.container}>
        <TouchableOpacity onPress={this.selectPhotoTapped.bind(this)}>
          <View style={[styles.avatar, styles.avatarContainer, { marginBottom: 20 }]}>
          { this.state.avatarSource === null ? <Text>Select a Photo</Text> :
            <Image style={styles.avatar} source={this.state.avatarSource} />
          }
          </View>
        </TouchableOpacity>

        <TouchableOpacity
          style={{
          backgroundColor: 'yellow',
          width: 60,
          height: 20,
          marginTop: 20,
          justifyContent: 'center',
          alignItems: 'center' }}
          onPress={this.doUpload.bind(this)}
        >
          <Text>Upload</Text>
        </TouchableOpacity>

        <TouchableOpacity
        style={{
          backgroundColor: 'yellow',
          width: 60,
          height: 20,
          marginTop: 20,
          justifyContent: 'center',
          alignItems: 'center'
          }} onPress={this.props.cancel}
        >
          <Text>Cancel</Text>
        </TouchableOpacity>

      </View>
    );
  }
}
const styles = {
  container: {
    justifyContent: 'center',
    alignItems: 'center'
  },
  avatarContainer: {
    borderColor: '#9B9B9B',
    borderWidth: 1 / PixelRatio.get(),
    justifyContent: 'center',
    alignItems: 'center'
  },
  avatar: {
    borderRadius: 75,
    width: 150,
    height: 150
  }

};
export default connect(null, { captureProflieAvitar })(NewCamera);

电线的另一端是什么? - martinarroyo
我只是获取一个空数据的对象。我认为我的问题在于我没有正确地格式化提交的数据。 - Christopher Wirth
我在 API 中得到了状态码 200,但数据并没有传输过来。 - Christopher Wirth
“Content-Type” 头看起来很奇怪,你告诉服务器请求体将是 application/x-www-form-urlencoded 数据,但显然这不是你发送给服务器的内容。 - Xeijp
你解决了吗? - DevAS
如何在 React Native 应用中上传图像 https://tech-blog.maddyzone.com/reactnative/how-to-upload-image-in-react-native-app - Rituraj ratan
3个回答

13

这里有一个使用Fetch API上传图片的示例。

var photo = {
  uri: user.profilePicture,
  type: 'image/jpeg',
  name: 'photo.jpg',
};

var form = new FormData();
form.append("ProfilePicture", photo);

fetch(
  Constants.API_USER + 'me/profilePicture',
  {
    body: form,
    method: "PUT",
    headers: {
      'Content-Type': 'multipart/form-data',
      'Authorization': 'Bearer ' + user.token
    }
  }
).then((response) => response.json())
.catch((error) => {
  alert("ERROR " + error)
})
.then((responseData) => {
  alert("Succes "+ responseData)
}).done();

致谢 https://dev59.com/Oovda4cB1Zd3GeqPd8m5#36649457


4
你如何确定它一定是一个 image/jpeg 格式的图片?如果不是,ReactNative 或者在问题中提到的 ImagePicker 包如何获取该信息? - Trip
为了使属性动态化,您可以使用以下代码:photo = { name: response.fileName, type: response.type, uri: Platform.OS === 'android' ? response.uri : response.uri.replace('file://', ''), } - Claret Nnamocha

7
如果有人想使用React Native上传图像至Laravel,请尝试以下方法。我个人使用react-native-image-crop-picker和Axios。请注意,保留HTML标签。
//create object with uri, type, image name
var photo = {
    uri: IMAGE_PATH,
    type: 'image/jpeg',
    name: 'photo.jpg',
};

//use formdata
var formData = new FormData(); 
//append created photo{} to formdata
formData.append('image', photo);
//use axios to POST
axios({
    method: 'POST',
    url: api_url +  'customer/upload-avatar',
    data: formData,
    headers: {
        'Authorization': "Bearer  "  +  YOUR_BEARER_TOKEN,
        'Accept': 'application/json',
        'Content-Type': 'multipart/form-data;'    
    }}) .then(function (response) { console.log(response)})
    .catch(function (error) { console.log(error.response)
});

1
非常有用 https://tech-blog.maddyzone.com/reactnative/how-to-upload-image-in-react-native-app - Rituraj ratan

0

如果你使用 react-native-image-picker 并尝试在 Laravel Restful API 上上传你的图片,请尝试以下方法。

// create a state for temp photo
const [photo, setPhoto] = React.useState(null);

// create a function to set a temp photo
const handleChoosePhoto = () => {
  launchImageLibrary({noData: true}, (response) => {
    if (response && !response.didCancel) {
      setPhoto(response);
    }
  });
};

// create a function to post your temp photo through api
const setData = () => {
  const formData = new FormData();
  if (photo) {
    const tempPhoto = {
      uri: photo?.assets[0]?.uri,
      type: photo?.assets[0]?.type,
      name: photo?.assets[0]?.fileName,
    };
    formData.append('avatar', tempPhoto);
  
    axios({
      method: 'POST',
      url: api_url +  'api/upload-avatar',
      data: formData,
      headers: {
        'Authorization': "Bearer " + YOUR_BEARER_TOKEN,
        'Accept': 'application/json',
        'Content-Type': 'multipart/form-data;'    
      }})
      .then((response) => { 
        console.log(response)
      })
      .catch((error) => {
        console.log(error.response)
      });
  }
}


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接