Asked  7 Months ago    Answers:  5   Viewed   34 times

I am trying to restrict direct access to files in a directory. So for example i have website.com/files/example.flv.

So if users go straight to the file in the URL, i want them to be redirected to the home page.

I have tried the following using htaccess

deny from all

but its not working great. Is there a way i could do this using php, then in the user goes straight to the file in the url, they will get redirected.

So if the user goes to the file link in the url, they will be sent to the home page. So can this only be done using htaccess

 Answers

87

If you want to restrict access to files, you should consider storing them outside the public DocumentRoot and using PHP to deliver the file, applying your own access logic. This means outside the www or public_html folders, depending on the hosting environment you are working with.

<?php

// Suppose your "public_html" folder is .
$file = './../data/test.gif';
$userCanDownloadThisFile = false; // apply your logic here

if (file_exists($file) && $userCanDownloadThisFile) {
    header('Content-Description: File Transfer');
    header('Content-Type: application/octet-stream');
    header('Content-Disposition: attachment; filename=filename.gif');
    header('Content-Transfer-Encoding: binary');
    header('Expires: 0');
    header('Cache-Control: must-revalidate');
    header('Pragma: public');
    header('Content-Length: ' . filesize($file));
    ob_clean();
    flush();
    readfile($file);
}
Wednesday, March 31, 2021
 
Bere
answered 7 Months ago
35

Send out a header defining the file's name.

$filename = $name . "." . $type;
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename=' . $filename);
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));

I've included additional headers, since you should send out these as well. This is just a modified example of what you can see in the PHP documentation on readfile.

Wednesday, March 31, 2021
 
petersaints
answered 7 Months ago
27

By the looks of it your file download script may be setting the wrong Content-Length, so that the last few bytes of the file can spill over into the next request, causing all manners of brokenness.

What web server and OS are you using, and how are you invoking PHP? Because if it's Windows I'd have a suspicion that your PHP installation may somehow be writing to stdout as a text instead of a binary stream. This would cause each n byte to be converted to a rn sequence, which would probably make most binary files unreadable as well as making the response body a bit longer than the Content-Length header said it was.

$parsed_url['localpath'] = LOCALROOT . $parsed_url['path'];

That seems rather dangerous. I would hope $filename were checked and validated to within an inch of its life before trying anything like that. (Filename validation is deceptively hard.)

Saturday, May 29, 2021
 
dimitarvp
answered 5 Months ago
65
RewriteCond %{HTTP_COOKIE} !mysessioncookie=([^;]+)
RewriteRule .+.(jpg|css|js) forbidden.html [R=403]
Friday, July 23, 2021
 
eek
answered 3 Months ago
eek
64

I suppose I wouldn't use a .htaccess (or any kind of HTTP-authentication) for that : .htaccess / .htpasswd are great when you want to allow/deny access to a whole directory, and not to specific files.


Instead, I would :

  • Deny any access to the files -- i.e. use a .htaccess file, containing Deny from All
    • That way, no-one has access to the file
    • Which means everyone will have to use another way to get to the files, than a direct URL.
  • Develop a PHP script that would :
    • receive a file identifier (a file name, for instance ; or some identifier that can correspond to the file)
    • authenticate the users (with some login/password fields), against the data stored in the database
    • if the user is valid, and has access to the file (This is if different users don't have access to the same set of files), read the content of the file from your PHP script, and send it the the user.

The advantage is that your PHP script has access to the DB -- which means it can allow users to log-in, log-out, it can use sessions, ...


About the "send the file from PHP", here are a couple of questions that might bring some light :

  • Sending correct file size with PHP download script
  • Resumable downloads when using PHP to send the file?
  • forcing a file download with php
Saturday, August 7, 2021
 
nikosd23
answered 3 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :