2

I want to download multiple files from the web using this code:

    var fs = require('fs');
    var http = require('http');
    var request = require('request');

    var file;
    for(var i = 1; i <= 5; i++) {
         //CHECK IF REMOTE FILE EXISTS
         request('http://webaddress.com/filename' + i + '.jar', function (err, resp) {

         //IF EXISTS DO
         if (resp.statusCode == 200) {
             //DOWNLOAD DATA AND CREATE A NEW .JAR FILE
             file = fs.createWriteStream('D:\\filename' + i + '.jar');
             http.get('http://webaddress.com/filename' + i + '.jar', function(response) {
                  response.pipe(file);
                  file.on('finish', function() {
                      file.close();
                  });
             });
         }

         //FILE DOES NOT EXIST
         });
     }

The result I want is: multiple files downloaded with filenames filename1-5.jar. The result I am getting is just 1 file with filename filename5.jar (or the last value of the i var in the loop). What am I doing wrong?

5
  • 1
    Your request is asynchronous and it will execute only after your loop finishes hence the 5 from the filename. Commented Jul 16, 2018 at 11:47
  • I suspected so. Thanks. What can I do to make it work? Commented Jul 16, 2018 at 11:48
  • See this answer, it can help you solve your problem stackoverflow.com/a/19911657/8221063 Commented Jul 16, 2018 at 11:52
  • Thanks @LucasDuarte I'll check it out. Commented Jul 16, 2018 at 11:56
  • @lupu51nfactumN778, I have added an answer for you. Commented Jul 16, 2018 at 11:57

2 Answers 2

3

Like @Ionut said your requests are async so you need to wait for it

let fs = require('fs');
let request = require('request');

let download = (uri, filename) => {
    return new Promise ((resolve, reject) => {
        request.head(uri, function(err, res) {

            if (res.statusCode === 200) {
                request(uri).pipe(fs.createWriteStream(filename)).on('close', resolve);
            } else {
                reject(res.statusCode);
            }
        });
    });
};

let promises = [];

for(let i = 1; i <= 5; i++) {
    promises.push(download('http://webaddress.com/filename' + i + '.jar', 'D:\\filename' + i + '.jar'));
}

Promise.all(promises).then(() => {
    process.exit(0);
}); 
Sign up to request clarification or add additional context in comments.

Comments

2

Your request is asynchronous and it will execute only after your loop finishes hence the 5 from the filename. A solution for this is to threat your code separately by creating a new function and call it inside the loop:

var fs = require('fs');
var http = require('http');
var request = require('request');

var file;

function customRequest(i){

  //CHECK IF REMOTE FILE EXISTS
  return request('http://webaddress.com/filename' + i + '.jar', function(err, resp) {

    //IF EXISTS DO
    if (resp.statusCode == 200) {
      //DOWNLOAD DATA AND CREATE A NEW .JAR FILE
      file = fs.createWriteStream('D:\\filename' + i + '.jar');
      http.get('http://webaddress.com/filename' + i + '.jar', function(response) {
        response.pipe(file);
        file.on('finish', function() {
          file.close();
        });
      });
    }

    //FILE DOES NOT EXIST
  });

}

for (var i = 1; i <= 5; i++) {
   customRequest(i)
}

1 Comment

Thanks, your code does make 5 separate files. The issue I have now is that all data goes to just 1 random file, others are empty. Could this be that the function is executed too fast? I tried setTimeout without much luck.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.