React-native upload image to amazon s3

I want to upload images from my application to the S3 server. I have all the data and codes calculated (verified using curl on a computer), but I can’t figure out how to correctly call a “fetch”. I get the answer:

'At least one of the prerequisites you specified has not been met. Condition: Slave POST must be from an array of type-multipart / form-data '

How can I recreate form data in sample answers? There is no FormData to which I can add and then submit it, as in the example example.

EDIT: Thanks @ philipp-von-weitershausen, I welcome you to add this feature. However, I have some problems causing this. I get "Unsupported BodyInit type". Found because in fetch.js: "support.formData" returns false. What am I missing when I call a sample?

My sample code is:

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(); 
+5
source share
4 answers

Some people asked, so I post how I did it. This was done quite quietly, so if you have any comments or something really badly done, I am open to criticism;) The photo is read from the Roll camera and stored in "lastPhoto".

Uploading photos to the S3 server:

Step 1: Creating Data:

 _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 }); } 

Step 2: Submit Data:

  _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 }); }, 
+7
source

multipart/form-data React Native support (via the XHR API FormData) for mixed payloads (JS strings + image payload) is in operation. He should land on GitHub soon.

+5
source

@ Michał Zubrzycki Thank you, your code for uploading the picture worked for me with a few changes.

 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(); 
+2
source

Parameters 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" } } 

component:

 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> ); } } } 
+1
source

All Articles