5

I am trying to do a simple file upload from lambda to s3 using nodejs. The lambda execution works fine without any error, but s3 upload is not happening. Since there is no error, I am not able to debug the issue. Below is the snippet that I am trying.

var s3 = new AWS.S3();

var params = {
Bucket : "testbucketuploads",
Key : "test.txt",
Body : "Hello!"
}

s3.putObject(params, function(err, data) {
          if (err) console.log(err, err.stack); // an error occurred
          else     console.log(data);           // successful response
});

I have provided S3 access to the lambda role. When I try to execute the same from CLI, the upload works just fine.

naba
  • 171
  • 2
  • 5
  • Verify that AWS.Credentials().accessKeyId looks like an access key. This will verify that your role is assigned and the SDK is locating the credentials. – John Hanley Oct 03 '18 at 07:40

6 Answers6

9

Answer to an old post, but maybe it helps someone. I have looked for a solution on forums and ultimately found it in the docs for aws-sdk. Well, a couple of hours of try&fail can save you several minutes of reading the docs or READMEs. Anyway. First, I use s3.upload instead of s3.putObject. Afterwards, the function is asynchronous and if the lambda function terminates earlier, than the upload, there won't be any result nor any log whatsoever. The prettiest solution I came up with is:

const fs = require('fs');
const s3 = new AWS.S3()
const file = fs.readFileSync(someFilePath)
const bucket = "..."
const s3key = "..."
const uploadParams = {
    Bucket: bucket,
    Key: s3key,
    Body: file
};
//executes the upload and waits for it to finish
await s3.upload(uploadParams).promise().then(function(data) {
    console.log(`File uploaded successfully. ${data.Location}`);
}, function (err) {
    console.error("Upload failed", err);
})
//code continues synchronously here
...
return whatEver;

Alternatively, if you have and want to have an async handler, you can return the Promise itself. However, doing so, you will have less control of what happens inside the resolve and reject callbacks. I.e. console.log I had placed inside them did not write the logs into lambda's console along with the other logs in the handler, that were called outside of the callbacks (before the upload).

MiG
  • 111
  • 1
  • 5
  • Wow, spent a while looking for this answer! You can just do `await s3.upload(params).promise()` instead of using `.then()` and `.catch()` to keep it clean. – Turbotailz Jan 25 '21 at 04:29
0

The AWS documentation indicates you need to send a binary string in the Body parameter. Take a look at this blog post How to convert a binary string into a readable string and vice versa with Javascript and this SO thread for examples of how to prepare your data for S3.

Renato Byrro
  • 3,578
  • 19
  • 34
0

For some reason callback based calls aren't working in this case. However, For me the following has worked just fine:

await s3.putObject(params).promise();
Hardik Shah
  • 111
  • 7
0

I had the same error with serverless framework and found that I was missing a couple of lines in the serverless.yml file allowing it to process binary media types (streams).

provider:

name: aws

runtime: nodejs14.x

lambdaHashingVersion: 20201221

apiGateway:

binaryMediaTypes:

  - 'multipart/form-data'

https://moduscreate.com/blog/upload-files-to-aws-s3-using-a-serverless-framework/

0

The reason can be the lambda function is in SubnetType.PRIVATE_ISOLATED subnet.

I experienced the same situation and spent 3 hours, only to find the SubnetType problem.
If you want to access outside of the vpc, you must use other SubnetType.

Lagyu
  • 87
  • 5
-7

Remove async if used, for example:

correct :

exports.handler = (event) => {
    enter code here
}

wrong :

exports.handler = async (event) => {
    enter code here
}
Wai Ha Lee
  • 8,598
  • 83
  • 57
  • 92
  • This is completely wrong! `async` is not the problem. The problem is when `async` is used incorrectly. – Thales Minussi Apr 03 '19 at 07:04
  • Somebody has flagged this answer on the premise that it's not an answer, or that it's of very low quality - presumably because they thought it was incorrect. Neither flag is appropriate in this case - incorrect answers should be downvoted and/or commented on, not flagged. [From Review](https://stackoverflow.com/review/low-quality-posts/22645228). – Wai Ha Lee Apr 03 '19 at 07:37