javascript React-native 上传图片到亚马逊 s3
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/30737226/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
React-native upload image to amazons s3
提问by Micha? Zubrzycki
I want to upload images from my app to S3 server. I have all data and codes calculated (tested using curl on computer) but I can't figure out how to call 'fetch' correctly. I'm getting response:
我想将图像从我的应用程序上传到 S3 服务器。我计算了所有数据和代码(在计算机上使用 curl 测试),但我无法弄清楚如何正确调用“获取”。我得到回应:
'At least one of the pre-conditions you specified did not hold. Condition: Bucket POST must be of the enclosure-type-multipart/form-data'
'至少你指定的先决条件之一不成立。条件:Bucket POST 必须是enclosure-type-multipart/form-data'
How can I recreate form-data in react-natives fetch? There is no FormData to which I can append and then send it like in fetches example.
如何在 react-natives fetch 中重新创建表单数据?没有我可以附加的 FormData,然后像在 fetches 示例中那样发送它。
EDIT: Thanks @philipp-von-weitershausen, greate that you have added this feature. However I have some troubles calling it. I'm getting "Unsupported BodyInit type". Found that is because in fetch.js: "support.formData" returns false. What am I missing when I call fetch?
编辑:感谢@philipp-von-weitershausen,感谢您添加了此功能。但是我在调用它时遇到了一些麻烦。我收到“不支持的 BodyInit 类型”。发现是因为在 fetch.js: "support.formData" 返回 false。当我调用 fetch 时,我错过了什么?
My code example:
我的代码示例:
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();
采纳答案by Micha? Zubrzycki
Some people asked, so I'm posting how I did it. It was done quiet long time ago so if you have any comments or something is really bad done I'm open to critic ;) Photo is in read from cameraRoll and stored in 'latestPhoto'.
有人问,所以我发布了我是如何做到的。很久以前它就安静地完成了,所以如果你有任何评论或者做的事情真的很糟糕,我愿意接受批评;) 照片是从 cameraRoll 读取的,并存储在“最新照片”中。
Uploading photo to S3 server:
将照片上传到 S3 服务器:
Step 1: Generate data:
第 1 步:生成数据:
_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: Send data:
第 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 });
},
回答by Pir Shukarullah Shah
@Micha? Zubrzycki Thanks, your code for uploading picture worked for me with little changes.
@米查?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();
回答by Philipp von Weitershausen
multipart/form-data
support for React Native (via the XHR FormData
API) for mixed payloads (JS strings + image payloads) is in the works. It should land in GitHub soon.
multipart/form-data
FormData
对混合负载(JS 字符串 + 图像负载)的React Native(通过 XHR API)的支持正在开发中。它应该很快就会登陆 GitHub。
回答by blackchestnut
S3 options:
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>
);
}
}
}