I'm working on a React Native application where I'm trying to take images from a user's camera roll, convert them to a base64 string and store them to Amazon S3 for later use.
Following this blog post I'm able to take a user's camera roll and convert the images to base64: react-native-creating-a-custom-module-to-upload-camera-roll-images
I'm then sending the base64 string image data to a simple Express server I have set up to post the data to my Amazon S3 bucket.
// Only getting first img in camera roll for testing purposes
CameraRoll.getPhotos({first: 1}).then((data) => {
for (let i = 0; i < data.edges.length; i++) {
NativeModules.ReadImageData.readImage(data.edges[i].node.image.uri, (imageBase64) => {
// Does the string have to be encoded?
// const encodeBase64data = encodeURIComponent(imageBase64);
const obj = {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
'img': imageBase64
})
}
fetch('http://localhost:3000/saveImg', obj)
.then((res) => {
console.log(JSON.parse(res._bodyInit));
})
})
}
My imageBase64
variable in this instance is a pretty large string reading like: /9j/4AAQSkZJRgABAQAASABIAAD/4QBYRXhpZgAATU0AKgAAA...abX+Yub/API3zf8A7G2Z/wDqdiD/AExyf/kT5R/2Kst/9QqB0x6H6GuBbr1R6D2foz+ZT/gof/yep8bf934f/wDqC6PX96+Cn/JruFf+6z/6t8UfwP4wf8nM4n9Mq/8AVbRPjOv1I/OAoA//2Q==
With the ...
being several more characters.
I'm sending this base64 string to my express server and posting the data:
app.post('/saveImg', function(req, res) {
// this will be moved once testing is complete
var s3Bucket = new AWS.S3( { params: {Bucket: '[my_bucket_name]'} } );
// Do I need to append this string to the image?
var baseImg = 'data:image/png;base64,' + req.body.img;
var data = {
Key: test_img,
Body: req.body.img,
ContentEncoding: 'base64',
ContentType: 'image/png'
};
s3Bucket.putObject(data, function(err, data){
if (err) {
console.log(err);
console.log('Error uploading data: ', data);
} else {
res.send(data);
console.log('successfully uploaded the image!');
}
});
// res.send(base64data)
});
I successfully send the data to Amazon S3 and see my image file in the bucket however when I try to visit the link to see the actual image itself, or pull it into my React Native app, I get nothing.
ie If I visit the url to test_img
above after it's in Amazon S3 I get:
https://s3.amazonaws.com/my_bucket_name/test_img
This XML file does not appear to have any style information associated with it. The document tree is shown below.
<Error>
<Code>AccessDenied</Code>
<Message>Access Denied</Message>
<RequestId>BCE6E07705CF61B0</RequestId>
<HostId>
aF2l+ucPPHRog1QaaXjEahZePF0A9ixKR0OTzlogWFHYXHUMUeOf2uP7D/wtn7hu3bLWG8ulKO0=
</HostId>
</Error>
I've uploaded images manually to this same bucket and their links appear fine, and I'm additionally able to pull them into my React Native application with no problem for viewing.
My question is what am I doing wrong between getting the base64 string data and sending it to my Express server for saving to my bucket? Does the base64 string have to be encoded? Do I need to convert the base64 string to a Blob before sending it to Express?
Thanks for the help!