1

I'm new to Node and i'm really stuck.

I'm trying to make my web server to look up files in current directory and to display them in browser as links so i could download them.

However the list of files gets just updated with every request and displayed over and over. I can't use any frameworks or external components and i have been stuck on this for two days. I really have done a lot of research and tried a lot of things and still can't get it working.

I'm gonna add my last attempt's code below and if anyone could help me with even a little bit of information, it would be most appreciated. Thanks!

 var http = require("http");
 var fs = require("fs");
 var currentServerDir = ".";
 var port = 8080;
 var content = "";
 var server = http.createServer(handlerRequest).listen(8080);

 function handlerRequest(request, response) {
     fs.readdir(currentServerDir, function getFiles(error, items) {
         items.forEach(function getItems(item) {
             content += "<br><a href= " + "\" " + item + "\" " + ">" + item + "</a><br>";
         });
     });
     response.writeHead(200, {
         'Content-Type': 'text/html'
     });
     response.write(content);
     response.end();
 }

EDIT:

I followed Node.js Generate html

and borrowed some code from there. Now i can click on a file, but instead of downloading or viewing it just says "undefined".

    var http = require('http');
    var content
    function getFiles()
    {
    fs.readdir(currentServerDir, function getFiles(error, items)
    {
    items.forEach(function getItems(item)
    {
    content+= "<br><a href= " + "\" " + item + "\" " + ">" +item +        "</a><br>";
    });
    });
    }

    http.createServer(function (req, res) {
    var html = buildHtml(req);

    res.writeHead(200, {
   'Content-Type': 'text/html',
   'Content-Length': html.length,
   'Expires': new Date().toUTCString()
   });

       res.end(html);

   }).listen(8080);

   function buildHtml(req) {
   var header = '';
   var body = content;

    return '<!DOCTYPE html>'
    + '<html><header>' + header + '</header><body>' + body + '</body>    </html>';
    };
Community
  • 1
  • 1
  • you don't clear "content" variable for the new request. Move the "content" variable to handleRequest scope. See https://gist.github.com/alexeysmorkalov/c8fb7e7be72ce90788da – AlexS Aug 20 '15 at 08:46
  • Actually it's still not working. It ain't displaying anything :/ – lordoftherings Aug 20 '15 at 08:59
  • OK, I edited the gist, please checkout it again. Since readdir is async you should end up the request in it's callback. This resolves the list problem only. To make download link working you should think how would your server process "download" requests. I would you a framework like express. Or if you want to download from local file system, format the links with "file://" protocol. – AlexS Aug 20 '15 at 09:14
  • Alright, thanks man! The list itself is working fine now. Except download. I prefixed it with file://, but download still not working. But i'm on my way, so thanks again! – lordoftherings Aug 20 '15 at 09:51
  • hint - you should use absolute path, not just file name for the file:// protocol – AlexS Aug 20 '15 at 10:04

3 Answers3

1

There are a few issues in your code.

  1. You never call getFiles() resulting that content will never be filled
  2. Should you call getFiles() content will still be empty in the end because you use fs.readdir(). This is an async function and will not be able to fill content before it used to build your html page.
  3. You handle every request to your server the same, so you will not be able download any files because you will always just display your page.

You can fix the first 2 easy by using the gist AlexS posted as a comment on your question. The third one will require a bit more setup, but can be made easy if you use Express.

Sonaryr
  • 1,092
  • 1
  • 10
  • 24
0

You could add the download tag to your HTML link :

items.forEach(function getItems(item)
{
   content+= "<br><a href= " + "\" " + item + "\" " + " download>" +item +        "</a><br>";
});

MDN reference

Limezest
  • 130
  • 2
  • 8
0

If you dont care about browser support you can use the download attribute in the a tag. It looks like this :

<a href="test.html" download="nameOfFileAfterDL">DL me!</a>

Supported by Firefox 14+ and Chrome 20+

But if you want a general solution then, you can zip your files before sending them, as far as I know .zip are always downloaded when "clicking on them".

You can use 'node-zip or archiver to zip your files.

Lauromine
  • 1,453
  • 9
  • 19
  • Download attribute not working, but with 'node-zip' - it's like an assignment and i can really use only out-of-the-box modules. – lordoftherings Aug 20 '15 at 08:51