API Gateway + Lambda download CSV file

14,079

Solution 1

If you can't fix it on the Lambda function, you could probably do a replaceAll() in the API Gateway mapping template. I think this could work just to replace the escaped double quotes:

$input.body.replaceAll("\\""","")

Edit: So the swagger would be (if I got the escaping right):

"responses": {
    "default": {
      "statusCode": "200",
      "responseParameters": {
        "method.response.header.Content-disposition": "'attachment; filename=testing.csv'"
      },
      "responseTemplates": {
        "text/csv": "$input.body.replaceAll(\"\\\"\"\",\"\")"
      }
    }
  }

Solution 2

Serverless has changed a bit since you asked this question but if you're using the lambda_proxy method of integration, you can use a handler like:

module.exports.handler = (event, context, callback) => {
  const csvRows = [
    '1,"blah",123',
    '2,"qwe",456'
  ]
  const result = csvRows.reduce((prev, curr) => {
    return prev + '\n' + curr
  })
  callback(null, {
    headers: {
      'Content-Type': 'text/csv',
      'Content-disposition': 'attachment; filename=testing.csv'
    },
    body: result,
    statusCode: 200
  })
}

Note: I've used ES6 features so you'll want to use Node 6 or higher to directly copy-paste this example.

Share:
14,079
Jim
Author by

Jim

Updated on June 27, 2022

Comments

  • Jim
    Jim almost 2 years

    I want to do a csv download link with API Gateway + Lambda. But there is a problem that lambda always return JSON.stringify. Is there a way to resolve this?

    s-function.json

    "responses": {
        "default": {
          "statusCode": "200",
          "responseParameters": {
            "method.response.header.Content-disposition": "'attachment; filename=testing.csv'"
          },
          "responseTemplates": {
            "text/csv": ""
          }
        }
      }
    

    handler.js

    var json2csv = require('json2csv');
    module.exports.handler = function(event, context, cb) {
       var fields = ['car', 'price', 'color'];
       var myCars = [
        {
          "car": "Audi",
          "price": 40000,
          "color": "blue"
        }, {
          "car": "BMW",
          "price": 35000,
          "color": "black"
        }, {
          "car": "Porsche",
          "price": 60000,
          "color": "green"
        }
       ]; 
        var csv = json2csv({ data: myCars, fields: fields });
        return cb(null, csv);
    };
    

    In the downloaded csv file.

    "\"car\",\"price\",\"color\"\n\"Audi\",40000,\"blue\"\n\"BMW\",35000,\"black\"\n\"Porsche\",60000,\"green\""

    Updated:

    I still trying but thank you at least I have direction. By the way, I can't find API Gateway doc about $input.body.replaceAll. replaceAll is Java function?

    Finally, I resolve this by below code in Api Gateway template.

    $input.body.replaceAll("\\""","").replaceAll("""","").replaceAll("\\n","
    ")
    

    s-function escaped double quotes.

    "responseTemplates": {
        "text/csv": "$input.body.replaceAll(\"\\\\\"\"\",\"\").replaceAll(\"\"\"\",\"\").replaceAll(\"\\\\n\",\"\n\")"
    }
    

    return data:

    car,price,color
    Audi,40000,blue
    BMW,35000,black
    Porsche,60000,green
    

    The template final replaceAll is weird. CSV don't recognize \n or \r\n, but I try copy new line in IDE and pass to code. It work and it's magical.

  • Jim
    Jim over 7 years
    Thank you let me have a direction! I update the question!
  • Tom Saleeba
    Tom Saleeba over 5 years
    @roll, not sure what happened to those quotes, they were horrible. Sorry about that, I've fixed it up.
  • Atul Sharma
    Atul Sharma almost 5 years
    Finally, After 6 hours. Worked like charm ! But, remember it will only work for files upto 6MB.