Raphael Rafatpanah Raphael Rafatpanah - 6 months ago 14
AngularJS Question

Serve PDF only on a successful form submit

What is the simplest way to set up a MEAN stack application to download a PDF attachment only on successful form completion?

Note: there is no user management. Everyone is able to view this form. If they successfully fill it out, they should be able to download the form. However, we don't want the URL to be shareable in an email, for example. The only way to get the PDF is to fill out the form. (Of course, the PDF could be emailed to anyone from there, but this is fine.)

Currently, the PDF can only be downloaded by visiting a NodeJS/express endpoint like so:

app.get('/endpoint', function(req, res) {
res.setHeader('Content-disposition', 'attachment;');
res.setHeader('Content-type', 'application/pdf');
var file = __dirname + '/pdf/ebook.pdf';
res.download(file);
});


The /pdf directly is not accessible publicly.

Some thoughts on how this could be done:


  1. Each visitor of the website receives a special key, and if they fill out the form correctly, visiting '/specialkey' becomes a temporary endpoint to download the ebook. Then in the client,
    $window.location.assign('/specialkey');
    would be executed to download the ebook.



However, I'm not sure what the best way to send the key to each unique user is. Also, it seems overly complicated for something that is conceptually simple. "Serve the ebook only on a successful form submit."

Has anyone come across this before?

Answer

How about after successful form posting to generate token document (in this answer I assume that You use mongo) and just to navigate to url with key:

window.location.href = '/download/sometokenhere';

and in server side:

app.get('/download/:token', function(req, res) {
    // for example we use mongodb with mongoose
    TokenModel
     .find({token: req.params.token})
     .count()
     .exec(function(err, count) {
        if(err || parseInt(count) == 0) {
          return res.redirect('/');
          // or: return res.status(403).send('Forbidden');
        } 

        res.setHeader('Content-disposition', 'attachment;');
        res.setHeader('Content-type', 'application/pdf');
        var file = __dirname + '/pdf/ebook.pdf';
        res.download(file);
      });
});

or You can set:

req.session.downloadToken = md5(new Date().getTime());

and in download route just check if token is equal to:

req.session.downloadToken

there are many ways...

another way is when form is ok then to return json response with downloadLink in it, and just navigate to the url that will be treated as file to download.

Comments