64

With Express.js is there a way to display a file/dir listing like apache does when you access the URL of a directory which doesn't have a index file - so it displays a listing of all that directories contents?

Is there an extension or package that does this which I don't know of? Or will I have to code this myself?

ggorlen
  • 44,755
  • 7
  • 76
  • 106
balupton
  • 47,113
  • 32
  • 131
  • 182

6 Answers6

66

As of Express 4.x, the directory middleware is no longer bundled with express. You'll want to download the npm module serve-index.

Then, for example, to display the file/dir listings in a directory at the root of the app called videos would look like:

    var serveIndex = require('serve-index');

    app.use(express.static(__dirname + "/"))
    app.use('/videos', serveIndex(__dirname + '/videos'));
jbll
  • 1,156
  • 1
  • 11
  • 14
  • Thanks for this. Extra question, if I'm serving a folder (as the root), then serving 2 directories (located elsewhere) as subfolders, they don't get listed when browsing the root. Anyway of fixing this? – ianbeks Oct 02 '15 at 09:02
  • 1
    Serve index doesn't allow to download the file , is there any way to download files from serve Index – ArUn Jun 02 '16 at 06:09
46

There's a brand new default Connect middleware named directory (source) for directory listings. It has a lot of style and has a client-side search box.

var express = require('express')
  , app = express.createServer();

app.configure(function() {
  var hourMs = 1000*60*60;
  app.use(express.static(__dirname + '/public', { maxAge: hourMs }));
  app.use(express.directory(__dirname + '/public'));
  app.use(express.errorHandler());
});

app.listen(8080);
Edison
  • 870
  • 1
  • 13
  • 28
yonran
  • 18,156
  • 8
  • 72
  • 97
  • 14
    I suggested an edit which was rejected for reasons beyond my understanding. > Since express got to 3.x `express.createServer()` is deprecated and should be replaced by `express()`. (see [change log](https://github.com/visionmedia/express/wiki/Migrating-from-2.x-to-3.x) for more details) – Jérémie Parker Oct 17 '13 at 15:14
  • 10
    The directory middleware has been split out and is now found here: https://github.com/expressjs/serve-index – gdw2 Aug 08 '14 at 20:00
  • I am getting errors not only on .createServer() as @JeremieParker describes but also on .configure(); – Coded Container Oct 16 '15 at 14:27
  • 5
    that link is now a 404 – callum Mar 21 '16 at 23:31
15

The following code will serve both directory and files

var serveIndex = require('serve-index');
app.use('/p', serveIndex(path.join(__dirname, 'public')));
app.use('/p', express.static(path.join(__dirname, 'public')));
Talespin_Kit
  • 20,830
  • 29
  • 89
  • 135
  • 2
    This is an important thing to call out! It's not immediately obvious in the accepted answer that the files are accessible because the `serveIndex` root is below the static root. Thanks! – Ada Richards May 12 '16 at 15:48
  • is there a way to make the listing chronological instead of alphanumerical with this? – fbence May 17 '16 at 13:16
  • `serveindex` serves both directory and files without this extra line as far as I'm aware.. – 1252748 Oct 19 '16 at 15:41
12

This will do the work for you: (new version of express requires separate middleware). E.g. you put your files under folder 'files' and you want the url to be '/public'

var express = require('express');
var serveIndex = require('serve-index');
var app = express();

app.use('/public', serveIndex('files')); // shows you the file list
app.use('/public', express.static('files')); // serve the actual files
Xin
  • 33,823
  • 14
  • 84
  • 85
3

Built-in NodeJS module fs gives a lot of fine-grained options

const fs = require('fs')

router.get('*', (req, res) => {
    const fullPath = process.cwd() + req.path //(not __dirname)
    const dir = fs.opendirSync(fullPath)
    let entity
    let listing = []
    while((entity = dir.readSync()) !== null) {
        if(entity.isFile()) {
            listing.push({ type: 'f', name: entity.name })
        } else if(entity.isDirectory()) {
            listing.push({ type: 'd', name: entity.name })
        }
    }
    dir.closeSync()
    res.send(listing)
})

Please make sure to read up on path-traversal security vulnerabilities.

Matteljay
  • 620
  • 5
  • 13
  • Please only use hand crafted solutions like this on development environment, do not use it in production. – Vitim.us Jun 03 '20 at 15:50
0

How about this code? Simple and can download files. I found in here.

var express    = require('express')
var serveIndex = require('serve-index')

var app = express()

// Serve URLs like /ftp/thing as public/ftp/thing
// The express.static serves the file contents
// The serveIndex is this module serving the directory
app.use('/ftp', express.static('public/ftp'), serveIndex('public/ftp', {'icons': true}))

// Listen
app.listen(3000)
Kian
  • 9
  • 2
  • Your answer could be improved by adding more information on what the code does and how it helps the OP. – Tyler2P Jun 09 '22 at 15:59