0

Trying to do something seemingly basic.

I'd like to create a POST request through which I'll be sending JSONs. These JSONs will be created into files, which I'd like to return to the user via download.

The use case for this is that I'm building an application which takes a form and converts it into a JSON for upload to a MongoDB database. Users can load these JSONs into the application to re-load their old records as templates.

This is how I'm approaching it as of now:

// Download JSON Previews
var jsondownload = {};

// Grabs the JSON from POST request
app.post('/api/download', function(req, res, next){
    jsondownload = {};
    var json = req.body;
    jsondownload = json;
    res.json(jsondownload);
    next();
});

// Immediately downloads the JSON thereafter
app.get('/api/download', function(req, res){
    res.set({"Content-Disposition":"attachment; filename='test.json'"});
    res.send(jsondownload);
});

What's the right way to do this?

Ahmed Haque
  • 7,174
  • 6
  • 26
  • 33
  • @KevinB, thanks for the input. I'd worried about this race condition issue as well. I'll use the strategy you suggested to get around it. – Ahmed Haque Dec 01 '15 at 20:08
  • I don't quite understand the usecase here, and because of that i can't really recommend how you should modify it. As it is, it would only ever work properly for a single user. Once a second user gets involved, the jsondownload variable will be shared between the two, thus causing conflicts. – Kevin B Dec 01 '15 at 20:08

1 Answers1

1

There is no one "right" way to do it, but a few solutions include:

  1. Remove the GET route handler (and the jsondownload variable) completely and just respond immediately with the Content-Disposition set appropriately. This is the better of the 3 because it reduces code and keeps things simple.

  2. Use a simple redirect in your POST route handler. Instead of responding with the JSON immediately, you would do res.redirect('/api/download').

  3. Do more or less what currently doing, but move the logic (the res.set() and res.send()) to a separate function that gets called from both route handlers.

mscdex
  • 104,356
  • 15
  • 192
  • 153
  • Thanks for the response. My hope is that option #1 was possible as well, however, when I try to use: "res.set({'Content-Disposition"...)" and "res.send(...)" in the POST request -- the download isn't triggered the same way it is with the GET request. Should it work the same between the POST and get? – Ahmed Haque Dec 01 '15 at 20:18
  • Seems someone was asking something similar and also didn't have much luck downloading files from POST requests http://stackoverflow.com/questions/29743395/express-js-how-to-download-a-file-using-post-request – Ahmed Haque Dec 01 '15 at 20:22
  • 1
    It's definitely possible, I've done it myself before (send an "attachment" response to a `POST` request). You might be missing additional headers or something depending on the browser. Try adding some extra headers shown [here](http://stackoverflow.com/a/16086443) or [here](http://stackoverflow.com/a/8485963). You might also try modifying the `filename` parameter so that it doesn't use single/double-quotes. – mscdex Dec 01 '15 at 20:49