直接从ReactNative(iOS)发布到带有签名请求的AWS S3

我正在尝试重新创build在React Native中上传用户提交图像的Heroku示例 ,但不断收到来自AWS的400个错误。

这些图像来自iOS相机胶卷。 我有这个图像的uri和一个base64编码的图像版本。 MIMEtypes是image/jpeg 。 到目前为止,我已经把所有东西都设置成了Heroku所说的,但是我无法使文件发送正确的形状。 我在下面添加了我的代码以进行说明。

我正在使用react-native-image-picker从相机胶卷中select图像

客户端代码

 module.exports = React.createClass({ ... openPhotos() { // called on a button press, opens camera roll ImagePicker.showImagePicker(options, (response) => { if (response.didCancel) return; if (response.error) return Alert.alert('ImagePicker Error: ', response.error); this.getSignedRequest(response); }); }, getSignedRequest(pickerResp) { // image uri IS pickerResp.uri AS IS `data:image/jpg;base64,${pickerResp.data}` var file = { uri: pickerResp.uri, // ALSO WORKS `data:image/jpg;base64,${pickerResp.data}`, name: `${this.props.email}.jpg`, type: 'image/jpeg' }; var body = new FormData(); body.append('file', file); fetch(`${api.TEST_API}sign-s3?file-name=${file.name}.jpg&file-type=${file.type}`, { method: "GET" }).then(response => response.json()).then(data => { Alert.alert("GOT SIGNED REQUEST",data.url); fetch(data.signedRequest, { method: 'put', body: body }).then(resp => resp.json()).then(data => { this.setState({uploadedFile: true}); this.props.toSignup(); }).catch(err => Alert.alert("Server Error", "Could not upload profile photo.")) }).catch(err => { Alert.alert('S3 Signed Request Error',"Look at the Logs"); console.log(err); }) }, ... }; 

服务器端代码

AWS NPM软件包:[aws-sdk]

 // get signature to upload client side to s3 apiRouter.get('/sign-s3', function(req, res) { console.log('signing s3') const s3 = new aws.S3(); // automatically loads key and secret const fileName = req.query['file-name']; const fileType = req.query['file-type']; const s3Params = { Bucket: S3_BUCKET, Key: fileName, Expires: 60, ContentType: fileType, ACL: 'public-read' }; s3.getSignedUrl('putObject', s3Params, (err, data) => { if(err) return console.log(err) const returnData = { signedRequest: data, url: `https://${S3_BUCKET}.s3.amazonaws.com/${fileName}` }; console.log(returnData) res.json(returnData); }); }); 

fetch(`${api.TEST_API}sign-s3?file-name=${file.name}.jpg&file-type=${file.type}

此处的获取请求将在所描述的文件名的末尾添加一个额外的.jpg ,因此当您尝试上传到S3时,它将被拒绝,因为有效负载不符合之前的请求。 另外,Herokubuild议的XMLHttpRequest可以正常工作,但是使用base64数据(下图)。

 var file = { uri: `data:image/jpg;base64,${pickerResp.data}`, //pickerResp.uri, type: 'image/jpeg', name: `${this.props.email}.jpg`, }; 

以下XML HTTP请求将以其编码forms将图像发送到S3,在S3中,简单的GET请求或图像src属性可以访问该文件。

 function uploadFile(file, signedRequest, url, cb) { const xhr = new XMLHttpRequest(); xhr.open('PUT', signedRequest); xhr.onreadystatechange = function() { if (xhr.readyState === 4) { if(xhr.status === 200) { cb() } else { alert('Could not upload file.'); } } }; xhr.send(file); };