【问题标题】:React-native upload image to amazons s3React-native 上传图片到 amazon s3
【发布时间】:2015-08-24 13:51:00
【问题描述】:

我想将图像从我的应用上传到 S3 服务器。我计算了所有数据和代码(在计算机上使用 curl 测试),但我无法弄清楚如何正确调用“获取”。我得到了回应:

'您指定的前提条件中至少有一个不成立。条件:bucket POST 必须是enclosure-type-multipart/form-data'

如何在 react-natives fetch 中重新创建表单数据?没有我可以附加的 FormData,然后像 fetches 示例中那样发送它。

编辑: 感谢@philipp-von-weitershausen,感谢您添加了此功能。但是我在调​​用它时遇到了一些麻烦。我得到“不支持的 BodyInit 类型”。发现是因为在 fetch.js: "support.formData" 返回 false。当我调用 fetch 时,我错过了什么?

我的代码示例:

 var form = new FormData();
 form.append("FormData", true)
 form.append("name", this.state.invoiceNumber)
 form.append("key", this.state.invoiceNumber)
 form.append("Content-Type", "image/png")
 form.append('file', this.props.uri)
 //alert(FormData.prototype.isPrototypeOf(form))

  fetch(amazon_url,{body: form,mode: "FormData", method: "post", headers: {"Content-Type": "multipart/FormData"}})
          .then((response) => response.json())
          .catch((error) => {
             alert("ERROR " + error)
          })
          .then((responseData) => {
             alert("Succes "+ responseData)
          })
          .done();

【问题讨论】:

  • 您有最终工作代码的示例吗?我也遇到了麻烦。
  • 事实上,你有没有一个例子可以发布表单变量(没有图像 - 看到下一个 RN 构建添加图像支持)。
  • react-native-fetch-blob 可以为您做到这一点。

标签: javascript file-upload amazon-s3 fetch react-native


【解决方案1】:

multipart/form-data 对混合有效负载(JS 字符串 + 图像有效负载)的 React Native(通过 XHR FormData API)的支持正在开发中。它应该很快就会登陆 GitHub。

【讨论】:

  • 太棒了!!我看到你也改变了调用 fetch 的方法?它停止工作或显示错误:Undiefiened 不是函数(评估 RCTDataMenager.queryData('http', { methode: method, url: url, data: data, headers: headers })。任何机会快速提示发生了什么变化?
  • 没关系,我有两个版本的 react-native 并且在这个文件夹中彼此不喜欢......
【解决方案2】:

有人问,所以我发布了我是如何做到的。它很久以前就安静地完成了,所以如果你有任何 cmets 或者做得真的很糟糕,我愿意接受批评;) 照片从 cameraRoll 中读取并存储在 'latestPhoto' 中。

上传照片到 S3 服务器:

第一步:生成数据:

_addTextParam() {
    var textParams = this.state.textParams;
    s3_upload_id = this.makeid()
    textParams.push({ name: "key", value: this.state.upload_path + s3_upload_id + '/' + this.state.att_name + ".jpg" })
    textParams.push({ name: "AWSAccessKeyId", value: this.state.key })
    textParams.push({ name: "acl", value: "public-read" })
    textParams.push({ name: "success_action_status", value: "201" })
    textParams.push({ name: "policy", value: this.state.policy })
    textParams.push({ name: "signature", value: this.state.signature })
    textParams.push({ name: "Content-Type", value: "image/jpeg" })

    this.setState({ textParams: textParams });
  }

第 2 步:发送数据:

  _send() {

    this._addTextParam()
    var xhr = new XMLHttpRequest();
    xhr.open('POST', "http://" + this.state.fs_domain + "." + this.state.server);
    xhr.onload = () => {
      this.setState({ isUploading: false });
      if (xhr.status !== 201) {
        AlertIOS.alert( 
          'Upload failed',
          'Expected HTTP 200 OK response, got ' + xhr.status + "/" + xhr.responseText
        );
        return;
      }

      if (!xhr.responseText) {
        AlertIOS.alert(
          'Upload failed',
          'No response payload.'
        );
        return;
      }
      var index = xhr.responseText.indexOf( "http://" + this.state.fs_domain + "." + this.state.server);
      if (index === -1) {
        AlertIOS.alert(
          'Upload failed',
          'Invalid response payload.'
        );
        return;
      }
      var url = xhr.responseText.slice(index).split('\n')[0];
      this.state.s3_file_id = xhr.responseText.split('Tag>"')[1].split('"')[0]
      this.state.s3_file_path = xhr.responseText.split('Location>')[1].split('<')[0]
      this.setState({ isUploading: false });
      RCTDeviceEventEmitter.emit('Uploaded')

    };
    var formdata = new FormData();

    this.state.textParams.forEach((param) => {
        formdata.append(param.name, param.value)
      }
    );

    formdata.append('file', {...this.state.latestPhoto, name: (this.state.att_name+".jpg") });

    xhr.send(formdata);
    this.setState({ isUploading: true });

  },

【讨论】:

  • 您是如何生成签名的?我在网上找到的所有模块都依赖于一些节点功能,例如 httpfs
  • @HarryMoreno 照片由:CameraRoll 加载,我从我们用 Ruby on Rails 编写的主应用程序获取签名。但我认为您可以根据 AWS 文档重新创建它。
【解决方案3】:

@Michał Zubrzycki 谢谢,您上传图片的代码对我有用,只需稍作改动。

const photo = {
  uri: user.profilePicture,
  type: "image/jpeg",
  name: "photo.jpg"
};
const 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 => {
    console.log("ERROR ", error);
  })
  .then(responseData => {
    console.log("Success", responseData);
  })
  .done();

【讨论】:

    【解决方案4】:

    S3 选项:

    // this.state.s3options in YourComponent
    {
      "url": "https://yourapp.s3.eu-central-1.amazonaws.com",
      "fields": {
        "key": "cache/22d65141b48c5c44eaf93a0f6b0abc30.jpeg",
        "policy": "eyJleHBpcm...1VDE0Mzc1OVoifV19",
        "x-amz-credential": "AK...25/eu-central-1/s3/aws4_request",
        "x-amz-algorithm": "AWS4-HMAC-SHA256",
        "x-amz-date": "20161125T143759Z",
        "x-amz-signature": "87863c360...b9b304bfe650"
      }
    }
    

    组件:

    class YourComponent extends Component {
      // ...
    
      // fileSource looks like: {uri: "content://media/external/images/media/13", isStatic: true}
      async uploadFileToS3(fileSource) {
        try {
          var formData = new FormData();
          // Prepare the formData by the S3 options
          Object.keys(this.state.s3options.fields).forEach((key) => {
            formData.append(key, this.state.s3options.fields[key]);
          });
          formData.append('file', {
            uri: fileSource.uri,
            type: 'image/jpeg',
          });
          formData.append('Content-Type', 'image/jpeg')
    
          var request = new XMLHttpRequest();
          request.onload = function(e) {
            if (e.target.status === 204) {
              // Result in e.target.responseHeaders.Location
              this.setState({avatarSourceRemote: {uri: e.target.responseHeaders.Location}})
            }
          }.bind(this)
          request.open('POST', this.state.s3options.url, true);
          request.setRequestHeader('Content-type', 'multipart/form-data');
          request.send(formData);
        } catch(error) {
          console.error(error);
        }
      }
    
      // Example display the uploaded image
      render() {
        if (this.state.avatarSourceRemote) {
          return (
            <Image source={this.state.avatarSourceRemote} style={{width: 100, height: 100}} />
          );
        } else {
          return (
            <Text>No Image</Text>
          );
        }
      }
    }
    

    【讨论】:

      【解决方案5】:
      //You need to Initialize Amplify in App.js
      
      import Amplify from 'aws-amplify';
      
      
      Amplify.configure({
        Auth: {
          identityPoolId: Config.AWS_COGNITO_IDENTITY_POOL_ID, //REQUIRED - Amazon Cognito Identity Pool ID
          region: Config.S3_REGION, // REQUIRED - Amazon Cognito Region
        },
        Storage: {
          AWSS3: {
            bucket: Config.S3_BUCKET,
            region: Config.S3_REGION,
          },
        },
      });
      
      
      // In your file
      
      import {Storage} from 'aws-amplify';
      
      export const S3UploadFile = async (uri, name, type) => {
        const file = await fetch(uri);
        const blob = await file.blob();
        const key = '/' + name;
      
        return Storage.put(key, blob, {
          contentType: type,
        });
      };
      

      【讨论】:

      猜你喜欢
      • 2010-11-26
      • 2020-06-04
      • 2018-06-08
      • 2017-06-29
      • 2018-11-24
      • 2019-05-15
      • 1970-01-01
      • 2015-06-20
      • 1970-01-01
      相关资源
      最近更新 更多