Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

API Gateway + Lambda download CSV file

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.

like image 400
Jim Avatar asked Jan 06 '23 15:01

Jim


1 Answers

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.

like image 56
Tom Saleeba Avatar answered Jan 08 '23 03:01

Tom Saleeba