Creating a Secure File Hosting Server for PDFs Creating a Secure File Hosting Server for PDFs php php

Creating a Secure File Hosting Server for PDFs


Put the files outside of the webroot. Then using PHP pass the file though a script. That way no one can link to the file directly and bypass your controls. (Naturally make sure the script that does this only after verifying the user has permission to retrieve that file).

Sample PHP:

<?php    session_start();    if (!isset($_SESSION['authenticated'])) {        exit;    }    $file = '/path/to/file/outside/www/secret.pdf';    header('Content-Description: File Transfer');    header('Content-Type: application/octet-stream');    header('Content-Disposition: attachment; filename=' . basename($file));    header('Content-Transfer-Encoding: binary');    header('Expires: 0');    header('Cache-Control: must-revalidate, post-check=0, pre-check=0');    header('Pragma: public');    header('Content-Length: ' . filesize($file));    ob_clean();    flush();    readfile($file);    exit;?>


The easy way is to give these files long random filenames (say, 20 random characters). Technically they will be accessible by anyone, but it will not be possible to guess the URL, so only authorized people will have access.

Alternatively John Conde already outlined a way to serve a file from a PHP script. It will incur a small performance penalty, but will be as secure as your code is. The only thing I can add is that if you cannot place them outside webroot, then you might be able to use .htaccess to prevent people from accessing the files directly.


John posted the primary correct way of doing it, so I'm adding the (probably inferior) alternative: Serve it from the database. Just have a BLOB column for the PDF, and read/store the file data from the database. You'll end up with a quite large table, but it will work. Serving it requires setting the same header()s as John posted, you just send off the data from the DB instead of from the file.

This has the advantage of not having to ensure you don't have filename collisions, etc.