我正在尝试重新创建 Heroku example在 React Native 中上传用户提交的图像,但不断从 AWS 收到 400 错误。
图片来自 iOS 相机胶卷。我有图像的 uri 和图像的 base64 编码版本。 MIME 类型是 image/jpeg
。到目前为止,我已经按照 Heroku 所述设置了所有内容,但在制作我发送的文件时遇到了问题。我在下面添加了我的代码以进行说明。
我正在使用 react-native-image-picker从相机胶卷中选择图像
客户端代码
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 时,它会被拒绝,因为负载与先前的请求不匹配.此外,Heroku 建议的 XMLHttpRequest 可以很好地处理您拥有的文件结构,但可以使用 base64 数据(如下)。
var file = {
uri: `data:image/jpg;base64,${pickerResp.data}`, //pickerResp.uri,
type: 'image/jpeg',
name: `${this.props.email}.jpg`,
};
以下 XML HTTP 请求会将图像以其编码形式发送到 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);
};
关于ios - 使用签名请求从 React Native (iOS) 直接发布到 AWS S3,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40443921/