AWS S3 upload file synchronously

I am using Meteor on Server side where I used Method Calls to return data.

So there I am trying to upload file to AWS S3 Bucket synchronously.

Here is a sample code:

Meteor.methods({

	uploadImage: function (params) {

		var AWS = Npm.require('aws-sdk');

		AWS.config.loadFromPath(process.env["PWD"]+'/private/awss3/s3_config.json');
		var s3Bucket = new AWS.S3( { params: {Bucket: 'users-profile-pictures'} } );

		buf = Buffer.from(params.baseimage.replace(/^data:image\/\w+;base64,/, ""),'base64')
		var data = {
		  Key: params.fileName, 
		  Body: buf,
		  ContentEncoding: 'base64',
		  ContentType: 'image/jpeg'
		};

		s3Bucket.putObject(data, function(err, data){
	        if (err) { 
	          console.log(err);
	          console.log('Error uploading data: ', data); 
	        } else {
	          console.dir(data);
	          console.log('successfully uploaded the image!');
	        }
	    });

	    return data;
	},
});

Now here I want to return the response I got from AWS SDK Callback. How can I make this upload synchronously?

Convert putObject function into a promise and await for the promise to resolve

As a suggestion, slingshot the file directly from client to S3 instead of uploading to meteor and then meteor to s3

When I use await, it gives me syntax error. I tried that already.
Plus I cant upload from client directly, off-course that would have been more easy, but due to some specific reasons I am bound to use Meteor server.

Did you convert it to a promise before using await?

I tried something like this:

const stored = await s3Bucket.putObject(data).promise();

What was the error that you received?

I forgot the requirements of AWS to use promises. But when I see callbacks, I normally create my own Promise function that I can await. I also use await-to-js to further make things synchronous.

Its says SyntaxError: line no . Unexpected Token

If the callback version is working, then I’ll go back to my original suggestion: Convert putObject function into a promise and await for the promise to resolve

(I mean here to create your own function that wraps putObject and return a promise)

I am not familiar with promise properly, can you help me understand this with my sample code?

You can find many sample in Google: “Convert callbacks to promises”

You could also use Meteor’s promise library, which allows you to do this:

import { Promise } from 'meteor/promise'

const result = Promise.await(someFunction())

This means that you don’t need to declare the enclosing function as async

1 Like

Do you need more S3 features than just simple uploads? If not, I’d highly recommend using edgee:slingshot. It’s super-easy and way less overhead than the official AWS SDK. Plus, it lets you upload the files directly from the client to S3.

2 Likes

I tried this, the file doesn’t upload to bucket. Also I dont know whats the error here

If you’re using await, the function it is in must be declared async too async function whatever() {}

1 Like

Or you could use Node.js util.promisify like this:

const util = Npm.require('util');
...
const s3BucketCB = function(err, data) {
  if (err) { 
    console.log(err);
    console.log('Error uploading data: ', data); 
  } else 
  ...
}

const promisifiedPutObject = util.promisify(s3Bucket.putObject);
return promisifiedPutObject(data, s3BucketCB);

This returns the data or, if an error occurs, takes it to the client as well.

Edit: wrong use of util.promisify fixed