Reputation: 137
I am building a MEAN stack application that uses Multer-s3 for uploading to Amazon bucket. It seems to be uploading images perfectly fine to the bucket in Amazon-S3 as well as database however when trying to get the images from Amazon (using ng-repeat) it gives following error:
GET https://s3-us-west-2.amazonaws.com/bucketfolder/bucketname/b40c4240-0417-11e6-9944-2d167e625d2b.jpg 403 (Forbidden)
in my mainController:
function mainController(Upload, API, S3_BUCKET, TokenService, User, $timeout) {
var self = this;
self.usersClothing = [];
self.uploadSingle = function() {
Upload.upload({
url: API + '/upload/single',
data: { file: self.file, type: self.clothingType }
})
.then(function(res) {
self.usersClothing = res.data.user.clothing.map(function(clothing) {
clothing.image = S3_BUCKET + clothing.image;
return clothing;
});
})
.catch(function(err) {
console.error(err);
});
}
My Angular state where I'm uploading images:
<div ng-repeat="clothing in main.usersClothing">
<img ng-src="{{clothing.image}}" class="clothing-img">
</div>
Upvotes: 2
Views: 2338
Reputation: 36043
In your upload code snippet (POST
), your code is executing on the server, and (I assume, you can confirm) using an IAM Instance Profile (role) or access keys to access your S3 bucket.
However, you are passing a URL to your S3 objects from the server to the client (browser). And it is the browser that is making the GET
request to S3 for the object. The browser does not have your AWS credentials.
So for the browser to download objects from the S3 bucket, the bucket and it's objects need to be public so they can be downloaded without authentication.
Example bucket policy:
{
"Version": "2008-10-17",
"Id": "Policy1397495964002",
"Statement": [
{
"Sid": "Stmt123",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::myBucketName/*"
}
]
}
Make sure you change the policy to replace your real bucket name.
This would not require any code changes on your part.
However, that means that your bucket is public to the world. To avoid this, you should generate a pre-signed URL for the client to use instead. Use s3.getSignedUrl
to generate a pre-signed URL and pass that URL to your client for download.
This would require some code changes to your server-side code.
Upvotes: 2
Reputation: 137
Fixed the issue: In my Amazon bucket I altered the preference for the image and set it to public. It was then able to make the GET request.
Upvotes: 0