Secure file storage

Hi all,

Search is running painfully slow, so apologies if this has been covered.

My application allows logged-in users to upload a PDF. For the sake of security, I am storing said PDFs outside of my web root. My folder ‘pdfs’ is on the same level as ‘htdocs’.

The users who upload the docs must also be able to download them. They’re operating within htdocs/admin/

On my offline server, linking to one of these pdfs using href=“…/…/pdfs/name.pdf” works fine. However, using my hosting company, it doesn’t work. Instead, it requests

Does anybody know why this might be? Is it a php configuration or perhaps a Linux thing?

Many thanks,

Files below the web root can never be accessed via the web, even if they are linked to that way. In order for people to download that file, you will have to pass it through some kind of script or proxy first that can check their logins and then stream the file contents to them like a normal download.

Just realised that the application within which I achieved it before does use a PHP script to achieve the link.

I’ll post back if I get it working.

Here’s how I got it to work:

Any links to these pdfs go through a php handler script. I’ve named it ‘secure-file.php’.

Link href values to pdfs within my htdocs/admin/ folder look like this:

The below is secure-file.php:

if($_GET['file'] == "") { redirect_to("index.php"); }
$pre = $_GET['file'];
$filename = "../../pdfs/" . $pre ;
if(!$file = fopen($filename, 'r')) { echo "File not found."; } else {

//set some HTTP headers 
Header('Content-Type: application/x-octet-stream'); 
Header('Content-Transfer-Encoding: binary'); 
Header('Content-Length: ' . filesize($filename)); 
Header('Cache-Control: no-cache, must-revalidate'); //HTTP 1.1 
Header('Cache-Control: post-check=0, pre-check=0', false); //HTTP 1.1 
Header('Pragma: no-cache'); //HTTP 1.0 
Header('Content-Description: Secure file'); 
Header('Content-Disposition: attachment; filename="'.$pre.'"'); 
Header('Title: ' .$filename); 

$fp = fopen($filename, 'r'); 

while(!$file) {
print(fread($file, 4096)); }


This downloads the file every time.