Search code examples
node.jsfile-uploadaws-lambdamultipartform-data

How to post file using aws Lambda using node.js


I need to read s3 file and send it to thirdparty api using Node.js V12 Labmda.

I am able to read the s3 file from bucket. But I have problem uploading that file to thirdparty url using https request or post method. I tried several methods but couldn't succeeded.

Here is my lambda sample code. Can you please review and guide me how can I resolve this issue.

const AWS = require('aws-sdk');
const http = require('https');
const querystring = require('querystring');

exports.handler = async function(event, context, callback) {
    const params = {
        Bucket: "bucket",
        Key: "filename"
    };
    var content = await s3.getObject(params).promise();
    await uploadFile("url", callback, content);
};

const uploadFile = async (url, callback, content) => {
    return new Promise((resolve, reject) => {

        var requestData = {};
        requestData['file'] = content;

        const postData = querystring.stringify(requestData);

        const options = {
            hostname: 'xxx.xxx',
            path: url,
            method: 'POST',
            headers: {
                'Content-Type': "multipart/form-data",
                'Content-Length': Buffer.byteLength(postData)
            }
        };

        const req = http.request(options, (res) => {

            res.on('data', (chunk) => {
                //do something
            });
            res.on('end', () => {
                // do something
            });
        })
        req.write(postData);
        req.end();

    });
}


Solution

  • I can see an example with requests module, maybe it could help:

    const AWS = require('aws-sdk');
    const http = require('https');
    const querystring = require('querystring');
    let request = require('request')
    
    exports.handler = async function(event, context, callback) {
        const params = {
            Bucket: "bucket",
            Key: "filename"
        };
        let readStream = s3.getObject(params).createReadStream()
        await uploadFile("url", callback, readStream);
    };
    
    const uploadFile = async (url, callback, readStream) => {
        return new Promise((resolve, reject) => {
    
            var requestData = {};
    
            const postData = querystring.stringify(requestData);
            
            let formData = {
              applicationType: 'my_app_type',
              applicationName: 'my_app_name',
              upload: {
                value: readStream,
                options: {
                  filename: 'my_file_name.zip', // adjust accordingly
                  contentType: 'application/zip' // adjust accordingly
                  knownLength: Buffer.byteLength(postData) // this is important
                }
              }
            }
            
            request.post({
              url: 'your_url',
              formData: formData
            }, function (error, response, body) {
              if (error) throw error
              console.log(body)
            });
    
        });
    }
    

    So, I kinda merged your snippet with this example, where the OP tries to PUT the content instead of POSTing it.

    Please note, however, that the code above is untested.