Upload files to Amazon S3 from the browser using pre-signed urls

npm install aws-sdk
const AWS = require(‘aws-sdk’);
const s3 = new AWS.S3({accessKeyId : config.aws_access_key_id, secretAccessKey : config.aws_secret_access_key, useAccelerateEndpoint: true});
const config = require(‘./config.js’).get(process.env.NODE_ENV);
sudo NODE_ENV=local node server
sudo NODE_ENV=dev node server
sudo NODE_ENV=prod node server
app.get(‘/generatepresignedurl’, function(req,res){
var fileurls = [];

/*setting the presigned url expiry time in seconds, also check if user making the request is an authorized user for your app (this will be specific to your app’s auth mechanism so i am skipping it)*/
const signedUrlExpireSeconds = 60 * 60;

setting the bucket name from config based on NODE_ENV, your dev and prod buckets should be different

const myBucket = config.s3bucketname;

change the name of your file based on your app logic

const myKey = ‘api/uploads/’ + ‘test.csv’;

set params for the getpresigned url request to Amazon S3

const params = {Bucket: myBucket, Key: myKey, Expires: signedUrlExpireSeconds, ACL: ‘bucket-owner-full-control’, ContentType:’text/csv’};

Since you will be using this presigned url for PUT it is extremely important to specify the ACL(Access Control List) and the ContentType

Now you are ready to call AWS SDKs awesome api to get your signed url

s3.getSignedUrl(‘putObject’, params, function (err, url){
if(err){
console.log(‘Error getting presigned url from AWS S3’);
res.json({ success : false, message : ‘Pre-Signed URL error’, urls : fileurls});
}
else{
fileurls[0] = url;
console.log(‘Presigned URL: ‘, fileurls[0]);
res.json({ success : true, message : ‘AWS SDK S3 Pre-signed urls generated successfully.’, urls : fileurls});
}
});
});
Encryption settings
{
“Version”: “2012–10–17”,
“Id”: “<policy-id>”,
“Statement”: [
{
“Sid”: “<sid>”,
“Effect”: “Allow”,
“Principal”: {
“AWS”: “arn:aws:iam::<awsaccount>:user/<awsusername>”
},
“Action”: “s3:*”,
“Resource”: “arn:aws:s3:::<s3-bucket-name>”
}
]
}
<?xml version=”1.0" encoding=”UTF-8"?>
<CORSConfiguration xmlns=”http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>POST</AllowedMethod>
<AllowedMethod>GET</AllowedMethod>
<AllowedMethod>PUT</AllowedMethod>
<AllowedMethod>DELETE</AllowedMethod>
<AllowedMethod>HEAD</AllowedMethod>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>
onSubmit() {//call node/express api endpoint to generate presignedurl/*fileService is nothing but a service injected into your angular component’s constructor like this constructor(private fileService: FileService) {}*/this.fileService.getpresignedurls().subscribe(res =>{console.log(res); // Your res object will have your pre-signed url//my res object is structured as success: boolean, message: string, urls: Array<string>;if(res.success){const fileuploadurl = res.urls[0];//once the presigned url is received the next service call will upload the file.this.fileService.uploadfileAWSS3(fileuploadurl, ‘text/csv’, this.yourform.get(‘filedetails’).value).subscribe((event: HttpEvent<any>) => {//handle HttpEvent progress or response and update view});}});}
getpresignedurls(): Observable<PreSignedURL>{
let getheaders = new HttpHeaders().set(‘Accept’, ‘application/json’);
return this.http.get<PreSignedURL>(this.getpresignedurlsserver, { headers: getheaders});
}

<PreSignedURL> is nothing but an interceptor that gives the structure of the response object I already mentioned.

uploadfileAWSS3(fileuploadurl, contenttype, file): Observable<any>{ //this will be used to upload all csv files to AWS S3 const headers = new HttpHeaders({‘Content-Type’: contenttype});
const req = new HttpRequest(
‘PUT’,
fileuploadurl,
file,
{
headers: headers,
reportProgress: true, //This is required for track upload process
});
return this.http.request(req);
}

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store