Prompt a csv file to download as pop up using node.js and node-csv-parser (node module)
Asked Answered
V

5

14

Recently I have started working with node.js. While going through a requirement in one of my projects I am facing an issue where I should be able to write some data to a csv file dynamically and let it prompt as a popup to download for user (with save and cancel options - as we normally see). After googling for some time I decided to use csv npm module https://github.com/wdavidw/node-csv-parser. I am able to write data into a file and save it using this module. I want to prompt a popup for saving this file with/without saving the file.

my code looks something like this:

    // Sample Data 
    var data = [["id", "subject1", "subject2", "subject3"], ["jack", 85, 90, 68], ["sam", 77, 89, 69]]

    // Server Side Code    
    var csv = require('../../node_modules/csv');            
    var fs = require('fs');

    createCSV = function(data, callback) {
        csv().from(data).to(fs.createWriteStream('D:/test.csv')) // writing to a file           
    }

    // Client side call sample
    $("#exportToCSV").click(function() {
        callToServer.createCSV(data);
       return false;
    });

This is working good as far as writing the csv file is concerned.

  • I want to prompt this file immediately to download for users.
  • If this can be done without saving the file, that will be great.
  • How can I set content-type and content-disposition as we do in PHP

Any help is greatly appreciated. -Thanks

Vitrescent answered 25/10, 2012 at 13:55 Comment(0)
V
15

I did it something like this :

http.createServer(function(request, response) {
    response.setHeader('Content-disposition', 'attachment; filename=testing.csv');
    response.writeHead(200, {
        'Content-Type': 'text/csv'
    });

    csv().from(data).to(response)

})
.listen(3000);
Vitrescent answered 8/11, 2012 at 7:44 Comment(3)
Just a note, once you complete the above server code, link your client side location.href to the node request url [no need for ajax call].Differentiate
A quick note on syntax for Express 4: res.setHeader('Content-disposition', 'attachment; filename=testing.csv'); res.set('Content-Type', 'text/csv'); res.status(200).send(csv);Estrellaestrellita
without csv library, and without express, instead of the csv() line, you can do response.write(myCSVText); resonse.end();Bulgarian
E
36

Manish Kumar's answer is spot on - just wanted to include a Express 4 syntax variant to accomplish this:

function(req, res) {
  var csv = GET_CSV_DATA // Not including for example.

  res.setHeader('Content-disposition', 'attachment; filename=testing.csv');
  res.set('Content-Type', 'text/csv');
  res.status(200).send(csv);

}
Estrellaestrellita answered 6/11, 2015 at 19:29 Comment(1)
I feel like it is confusing and inconsistent to mix setHeader with set. Even though they do the same thing, they come from different places. Using setHeader() comes from NodeJS's http module. If you use res.set, that is from the Express framework; it allows for setting multiple headers if you give it an object: res.set({ 'Content-Disposition': 'attachment; filename=testing.csv', 'Content-Type': 'text/csv' })Executrix
V
15

I did it something like this :

http.createServer(function(request, response) {
    response.setHeader('Content-disposition', 'attachment; filename=testing.csv');
    response.writeHead(200, {
        'Content-Type': 'text/csv'
    });

    csv().from(data).to(response)

})
.listen(3000);
Vitrescent answered 8/11, 2012 at 7:44 Comment(3)
Just a note, once you complete the above server code, link your client side location.href to the node request url [no need for ajax call].Differentiate
A quick note on syntax for Express 4: res.setHeader('Content-disposition', 'attachment; filename=testing.csv'); res.set('Content-Type', 'text/csv'); res.status(200).send(csv);Estrellaestrellita
without csv library, and without express, instead of the csv() line, you can do response.write(myCSVText); resonse.end();Bulgarian
S
12

Following solution is for Express

Express is evolved, instead of setting attachment and content type header, directly use attachment api http://expressjs.com/4x/api.html#res.attachment

Note: attachment() don't transfer the file, it just sets filename in header.

response.attachment('testing.csv');
csv().from(data).to(response);
Sharonsharona answered 16/6, 2014 at 11:38 Comment(0)
I
3

Express-csv is a great module for writing csv contents to stream from a node.js server, which will be sent as a response to the client (and downloaded as a file). Very easy to use.

app.get('/', function(req, res) {
  res.csv([
    ["a", "b", "c"]
  , ["d", "e", "f"]
  ]);
});

The docs: https://www.npmjs.com/package/express-csv

When you pass an object, you need to prepend the headers explicitly (if you want them). Here's my my example using npm mysql

router.route('/api/report')
    .get(function(req, res) {
            query = connection.query('select * from table where table_id=1;', function(err, rows, fields) {
                if (err) {
                    res.send(err);
                }
                var headers = {};
                for (key in rows[0]) {
                    headers[key] = key;
                }
                rows.unshift(headers);
                res.csv(rows);
            });
    });
Imperialism answered 9/2, 2015 at 1:5 Comment(0)
N
0

Check out this answer: Nodejs send file in response

Basically, you don't have to save the file to the hard drive. Instead, try sending it directly to the response. If you're using something like Express then it would look something like this:

var csv = require('csv');
req.get('/getCsv', function (req, res) {
    csv().from(req.body).to(res);
});
Nemato answered 25/10, 2012 at 18:29 Comment(2)
I am not using express, but just a custom framework of node.jsVitrescent
Either way, the http module responds to requests with callbacks of the same parameters, function (request, response). I think you should be able to send the results of the CSV directly to the response.Nemato

© 2022 - 2024 — McMap. All rights reserved.