Search code examples
node.jsamazon-web-servicesaws-lambdaaws-sdkaws-sdk-nodejs

Saving file to /tmp in lambda from inside of a folder


I have a task of downloading and uploading files to s3 using lambda, the scenerio is like

  • Download a file from s3 bucket1(request folder) to lambda
  • Upload the same file to s3 bucket2(request folder) from lambda

Both the downloadFiles and uploadFiles fn are inside utils/s3.js inside the root directory(var/task/) in lambda

Here is my utils/s3.js downloadFiles fn

exports.downloadFiles = async () => {
  try{
    const location = path.join( __dirname , `../tmp/text.txt`);
    console.log(location); // prints /var/task/tmp/text.txt
    console.log(__dirname); // prints /var/task/utils
    const params = {
      Bucket: 'bucket1',
      Key: `request/text.txt`
    };

    const { Body } = await s3.getObject(params).promise();
    fs.writeFileSync(location, Body);
    return;
  }catch(e){
    throw new Error(e.message);
  }
};

Now there are two cases,

  • If I create a folder in the root directory tmp, it gives this error

    "EROFS: read-only file system, open '/var/task/tmp/text.txt'"

  • If I don't then

    "ENOENT: no such file or directory, open '/var/task/tmp/text.txt'"

Now I have read most of the answeres on stackoverflow, I know I am supposed to save files to /tmp/filename, but how come I do the same and it doesn't work, where am I going so wrong?


Solution

  • As one commenter already stated, if you do not do anything with the file itself, it would be much better to just use the S3 API to copy the object instead of downloading and re-uploading it.

    The relevant documentation can be found here: https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#copyObject-property

    Example:

    var params = {
      CopySource: "/<source-bucket>/<source-key>", 
      Bucket: "<destination-bucket>",
      Key: "<destination-key>"
    };
    
    s3.copyObject(params, function(err, data) {
       if (err) console.log(err, err.stack); 
       else     console.log(data);
    });
    

    Or if you want to use a promise, this should work as well:

    var params = {
      CopySource: "/<source-bucket>/<source-key>", 
      Bucket: "<destination-bucket>",
      Key: "<destination-key>"
    };
    
    try {
        const result = await s3.copyObject(params).promise();
    } catch (error) {
        console.log(error);
    }