Styling a Server-Generated File Directory

Avatar of Keith Knittel
Keith Knittel on (Updated on )

The following is a guest post by Keith Knittel. Keith used a tutorial on this site to build his own customized file directory. I was like, hey, that oughta be a better-explained tutorial on this site. So here we are.

You likely know that if there is an “index.html” file in a directory on a server, it’s like to serve that file if the URL matches that directory. Like:

httpdocs
  - my_folder
    - index.html
    - cool_mountain.jpg

So if you went to:

http://thatwebsite.com/my_folder/

It would render `index.html`. But what if `index.html` (or the like) was missing? You can configure that behavior. You can configure it to deny access to that directory. Or you can allow it and have it spit out a browseable file directory (sort of like FTP).

That can be useful. Just upload files and they immediately appear, no code changes. But a bit boring.

Ethan Marcotte’s bukk.it is a classic example of a default directory.

They all look the same: an unstyled, sortable list. To build a directory that looks a little better, we’re going to use:

  • sortable.js
  • a line of code in our HTAccess
  • a little bit of PHP
  • and of course, some CSS

We’ll also use an easy way to “hide” certain files in our directory to keep them from showing up in our final file list. For context, here is a demo.

Preflight Check

First we’ll make sure the server is configured to show hidden files. We’ll be using file names like `.index.php` (Note the “.” at the start of the file name). An operating system-specific Google search will likely find you an answer. We’ll be using hidden files to make this work, so we’ll need to be able to see them to work with them. Having them be hidden means they ultimately won’t show up in the directory listing, which is generally preferable.

.htaccess

In our `.htaccess file`, we would could use Options +Indexes to display a directory, but we want to use a hidden index file so we can build our own page. We’ll use this instead to define the exact file we want to be responsible for displaying the file directory:

DirectoryIndex .index.php

It would be a good idea to add error redirects, but for the sake of this quick tutorial we’ll only add a 404. Aside: You can add any page in your directory in place of “.index.php” or “.404-error.php” and it will load that page. Neat.

ErrorDocument 404 .404-error.php

.index.php

Our `.index.php` file links up some assets. For instance, a script and a stylesheet. Even a favicon, if you’d like. All these files will start with a `.` so they don’t show up in the directory listing. Stuff in the head will be like:

<link rel="shortcut icon" href=".favicon.ico">
<link rel="stylesheet" href=".style.css">
<script src=".sorttable.js"></script>

A <table> element is a fair choice for a list of files and metadata, so we’ll go for that. That’s what sortable.js is for, anyway. Sortable is such an easy library to use, we just have the class of sortable on the table and it works. And here’s the basic PHP that reads all the files, loops through them, and outputs what is needed:

<table class="sortable">
  <thead>
    <tr>
      <th>Filename</th>
      <th>Type</th>
      <th>Size <small>(bytes)</small></th>
      <th>Date Modified</th>
    </tr>
  </thead>
  <tbody>
  <?php
    // Opens directory
    $myDirectory=opendir(".");

    // Gets each entry
    while($entryName=readdir($myDirectory)) {
      $dirArray[]=$entryName;
    }

    // Finds extensions of files
    function findexts($filename) {
      $filename=strtolower($filename);
      $exts=split("[/\\.]", $filename);
      $n=count($exts)-1;
      $exts=$exts[$n];
      return $exts;
    }

    // Closes directory
    closedir($myDirectory);

    // Counts elements in array
    $indexCount=count($dirArray);

    // Sorts files
    sort($dirArray);

    // Loops through the array of files
    for($index=0; $index < $indexCount; $index++) {

      // Gets File Names
      $name=$dirArray[$index];
      $namehref=$dirArray[$index];

      // Gets Extensions
      $extn=findexts($dirArray[$index]);

      // Gets file size
      $size=number_format(filesize($dirArray[$index]));

      // Gets Date Modified Data
      $modtime=date("M j Y g:i A", filemtime($dirArray[$index]));
      $timekey=date("YmdHis", filemtime($dirArray[$index]));

      // Print 'em
      print("
      <tr class='$class'>
        <td><a href='./$namehref'>$name</a></td>
        <td><a href='./$namehref'>$extn</a></td>
        <td><a href='./$namehref'>$size</a></td>
        <td sorttable_customkey='$timekey'><a href='./$namehref'>$modtime</a></td>
      </tr>");
    }
  ?>
  </tbody>
</table>

This is a simplified version. There is a more robust one here that cleans up file extensions, directories, hidden files, and more.

CSS

To style our directory, we can do whatever we like in our (hidden) `.style.css`. We could apply custom fancy icons like:

/* images */
table tr td:first-of-type a[href$=".jpg"],
table tr td:first-of-type a[href$=".png"],
table tr td:first-of-type a[href$=".gif"],
table tr td:first-of-type a[href$=".svg"],
table tr td:first-of-type a[href$=".jpeg"] {
  background-image: url(./.images/image.png);
}

You can do any styling you like! There is a collection of table designs over on CodePen.

The End

The beauty of this setup is it’s really easy to upload non-sensitive files and share them as fast as you can refresh the page and send a link. If for some reason you wish to revert to the default unstyled directory, you can simply go to the htaccess file and replace DirectoryIndex .index.php with Options +Indexes and your back to the default directory.

Demo

There is a demo right here on this site. I also used this exact technique to build a fun image directory of my own: asecrettoeverybody.com