how to serve a file (exe or rar ) to a client for download from node.js server?

I have a a node.js server that serves an index.html with a text input for a password. After a serverside password check the download should start for the client. The client shouldn't be able to see the location path where the file lies on the server.

here is my server.js:

var
    http = require('http'),
    qs = require('querystring'),
        fs = require('fs') ;
console.log('server started');

var host = process.env.VCAP_APP_HOST || "127.0.0.1";
var port = process.env.VCAP_APP_PORT || 1337;

http.createServer(function (req, res) {

    if(req.method=='GET') {

        console.log ( ' login request from    ' + req.connection.remoteAddress );



            fs.readFile(__dirname +'/index.html', function(error, content) {
                if (error) {
                    res.writeHead(500);
                    res.end();
                }
                else {
                    res.writeHead(200, { 'Content-Type': 'text/html' });
                    res.end(content, 'utf-8');
                }
            });


    }  // method GET  end

    else{ // method POST start


        console.log('POST request from   ' + req.connection.remoteAddress);
        var body = '';
        req.on('data', function (data) {
            body += data;

            if (body.length > 500) {
                // FLOOD ATTACK OR FAULTY CLIENT, NUKE REQUEST
                req.connection.destroy(); console.log('too much data')}
        });

        req.on('end', function () {

            var postdata = qs.parse(body);
            var password = postdata.passwordpost  ;


      if (password == '7777777') {
               console.log('the password is right, download starting');

             // ???????????????????????????????????                         here I need help from stackoverflow



      }


          else{
          console.log ('password wrong');
          fs.readFile(__dirname +'/wrongpassword.html', function(error, content) {
              if (error) {
                  res.writeHead(500);
                  res.end();
              }
              else {
                  res.writeHead(200, { 'Content-Type': 'text/html' });
                  res.end(content, 'utf-8');
              }
          });
      }
        });       // req on end function end

    }
}).listen(port, host);

the part where I need help is marked with ????????

here is my index.html:

<html>
<body>
<br>  <br>
&nbsp;&nbsp;&nbsp; please enter your password to start your download
<br>  <br>

<form method="post" action="http://localhost:1337">
    &nbsp;&nbsp;&nbsp;
    <input type="text" name="passwordpost" size="50"><br><br>
    &nbsp;&nbsp;&nbsp;   &nbsp;&nbsp;&nbsp; &nbsp;
    <input type="submit" value="download" />
</form>

</body>
</html>

Do you know how to do this?

Sure, you can use this in your code :

res.setHeader('Content-disposition', 'attachment; filename='+filename);
//filename is the name which client will see. Don't put full path here.

res.setHeader('Content-type', 'application/x-msdownload');      //for exe file
res.setHeader('Content-type', 'application/x-rar-compressed');  //for rar file

var file = fs.createReadStream(filepath);
//replace filepath with path of file to send
file.pipe(res);
//send file

You needs to declare and require the path: path = require("path")

then can do:

var uri = url.parse(request.url).pathname
    , filename = path.join(process.cwd(), uri);

path.exists(filename, function(exists) {
    if(!exists) {
        response.writeHead(404, {"Content-Type": "text/plain"});
        response.write("404 Not Found\n");
        response.end();
        return;
    }
response.writeHead(200);
response.write(file, "binary");
response.end();
}

check these complete example.

I found some additional information about fs.createReadStream() ( especially error handling ) here and combined it with the answer of user568109. Here is my working downloadserver:

var
    http = require('http'),
    qs = require('querystring'),
        fs = require('fs') ;
console.log('server started');

var host = process.env.VCAP_APP_HOST || "127.0.0.1";
var port = process.env.VCAP_APP_PORT || 1337;

http.createServer(function (req, res) {

    if(req.method=='GET') {

        console.log ( ' login request from    ' + req.connection.remoteAddress );



            fs.readFile(__dirname +'/index.html', function(error, content) {
                if (error) {
                    res.writeHead(500);
                    res.end();
                }
                else {
                    res.writeHead(200, { 'Content-Type': 'text/html' });
                    res.end(content, 'utf-8');
                }
            });


    }  // method GET  end

    else{ // method POST start


        console.log('POST request from   ' + req.connection.remoteAddress);
        var body = '';
        req.on('data', function (data) {
            body += data;

            if (body.length > 500) {
                // FLOOD ATTACK OR FAULTY CLIENT, NUKE REQUEST
                req.connection.destroy(); console.log('too much data')}
        });

        req.on('end', function () {

            var postdata = qs.parse(body);
            var password = postdata.passwordpost  ;


      if (password == '7777777') {
               console.log('the password is right, download starting');


          res.setHeader('Content-disposition', 'attachment; filename='+'test1.exe');
//filename is the name which client will see. Don't put full path here.

          res.setHeader('Content-type', 'application/x-msdownload');      //for exe file
          res.setHeader('Content-type', 'application/x-rar-compressed');  //for rar file

          var readStream = fs.createReadStream('/test1.exe');
//replace filepath with path of file to send
          readStream.on('open', function () {
              // This just pipes the read stream to the response object (which goes to the client)
              readStream.pipe(res);
          });

          // This catches any errors that happen while creating the readable stream (usually invalid names)
          readStream.on('error', function(err) {
              console.log (err)  ;
              res.writeHead(200, { 'Content-Type': 'text/html' });
              res.end('an error occured', 'utf-8');

          });
//send file



      }


          else{
          console.log ('password wrong');
          fs.readFile(__dirname +'/wrongpassword.html', function(error, content) {
              if (error) {
                  res.writeHead(500);
                  res.end();
              }
              else {
                  res.writeHead(200, { 'Content-Type': 'text/html' });
                  res.end(content, 'utf-8');
              }
          });
      }
        });       // req on end function end

    }
}).listen(port, host);

If you are willing to use express web framework, then it can be done in a much easier way.

app.get('/download', function(req, res){
  var file = __dirname + 'learn_express.mp4';
  res.download(file); // Sets disposition, content-type etc. and sends it
});

Express download API