0

We have a web application which upon visiting the url, will prepare and generate a .zip file which is then downloaded.

I need to create a nodejs application using requestjs that can keep making requests until there is an attachment header, from which point it would be downloaded.

The page which generates the .zip file contains a simple html message, stating that the file is being prepared for download. With a javascript reload(true) function called on load.

I'm not sure if this is the right way of doing it, but I am open to suggestions.

stackunderflow
  • 1,644
  • 6
  • 24
  • 40

1 Answers1

1

You could use async.until to loop through some logic until the header is available:

let success = true;
async.until(
    // Do this as a test for each iteration
    function() {
        return success == true;
    },
    // Function to loop through
    function(callback) {
        request(..., function(err, response, body) {
            // Header test
            if(resonse.headers['Content-Disposition'] == 'attatchment;filename=...') {
                response.pipe(fs.createWriteStream('./filename.zip'));
                success = true;
            }
            // If you want to set a timeout delay
            // setTimeout(function() { callback(null) }, 3000);
            callback(null);
        });
    },
    // Success!
    function(err) {
        // Do anything after it's done
    }
)

You could do it with some other ways like a setInterval, but I would choose to use async for friendly asynchronous functionality.

EDIT: Here's another example using setTimeout (I didn't like the initial delay with setInterval.

let request = require('request');

let check_loop = () => {
    request('http://url-here.tld', (err, response, body) => {
        // Edit line below to look for specific header and value
        if(response.headers['{{HEADER_NAME_HERE}}'] == '{{EXPECTED_HEADER_VAL}}') 
        {
            response.pipe(fs.createWriteStream('./filename.zip')); // write file to ./filename.zip
        }
        else
        {
            // Not ready yet, try again in 30s
            setTimeout(check_loop, 30 * 1000);
        }
    });
};

check_loop();
Ding
  • 3,065
  • 1
  • 16
  • 27
  • I can't seem to get your answer to work, do you have an example of using setInterval? – stackunderflow Oct 26 '16 at 04:19
  • I've updated my answer with another example. It was quick and dirty so you may need to tweak it a little bit. – Ding Oct 26 '16 at 04:44
  • Thanks for the answer, annoyingly your examples don't work because the requests are just repeated and the session isn't maintained. I'm not sure if I need to make additional requests from the first. Or use a stream to check the headers, so that the connection is maintained. – stackunderflow Oct 26 '16 at 05:41
  • You can try setting `jar` to `true` in your request parameters to save cookie data. That might help. – Ding Oct 26 '16 at 05:42
  • Thanks so it's working, the file is being downloaded .. However it's zerobytes. Does the `createWriteStream` need to be the name of the file? Becuase that is `filename-{random_number}.zip`. Would a wildcard help here i.e `filename-*.zip`. – stackunderflow Oct 26 '16 at 05:54
  • Or should that be `body.pipe(fs.createWriteStream('./filename.zip'))`? – stackunderflow Oct 26 '16 at 06:02
  • You might have to do something like http://stackoverflow.com/questions/11944932/how-to-download-a-file-with-node-js-without-using-third-party-libraries or http://stackoverflow.com/questions/17588179/node-js-request-download-file-sometimes-empty-or-no-existing – Ding Oct 26 '16 at 06:17
  • Thank you for all your help, I finally got it working with your solution. I had to use `fs.writeFile` and set encoding to null as mentioned here http://stackoverflow.com/questions/12029523/node-downloading-a-zip-through-request-zip-being-corrupted. – stackunderflow Oct 26 '16 at 07:16