Closed. This question is off-topic. It is not currently accepting answers.
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 10 years ago.
Improve this question
i have an uploads folder on my website.
What i want to do is restrict users from accessing like i dont want them to go to www.mysite.com/uploads/ and see the files in there and it should show forbidden, but they should be able to download via my website, for example www.mysite.com/downloads.php?id=1
If thats not possible, how can i atleast not show them the directory index on /uploads
How is it that file sharing websites does this?
An htaccess with
deny from all
stops php from accessing the file as well
Please tell me a solution if you would know, i googled and asked on irc a few days ago about this issue, its pretty confusing to me.
If you want to hide your file url from users, its better to move upload folder above of your webroot directory. So nobody can access from browser. How you make download.php
<?php
/*
Step 1. Authorization check
Step 2. get name or id of file that will download $_GET
Step 3. check if its valid (security check)
Step 4. check if that file exist in your upload directory
Step 5. set header using header() function put content-type, attachment etc
Step 6. readfile and output it
*/
?>
Add this line in your .htaccess file
Options -Indexes
Place an index.htm file in your uploads folder or place Options -Indexes in your .htaccess file
Why not just make a place for downloadable things (mkdir publicuploads), but chmod 700 your uploads folder?
Then they can download what you allow them to download...
Using a .htaccess file with deny from all will stop people accessing that folder, It wont stop php from accessing it, but you could put your files one directory lower then your htdocs/www/public_html folder and use php to grab and serve thos files.
With passing a parameter eg: ?id=1 you would access the 1 with $_GET['id'] you would need to check if the file exists, add some http headers to force the download.
Heres a simple example you can work on:
<?php
//your below webroot downloads folder
$path="/var/www/somehost.com/downloads/";
//An array created from globing the download directory or from a database source
$files=array('somefile.gif',
'someotherFile.png');
//In my example the id is the key to the file pathe array so 0 would be somefile.gif and 1 would be the next.
if(isset($_GET['id'])){
//Is it numeric?
if(is_numeric($_GET['id']) && isset($files[$_GET['id']])){
//Download the file, the download function will return error on fail, eg: not found or directory
$status = download($path.$files[$_GET['id']]);
//Spit out the error
if(isset($status['error'])){
die($status['error']);
}
}
}
function download($file,$chunk=1024){
if (file_exists($file)) {
if(is_dir($file)){return array('error'=>'Not allowed!');}
//Set content headers to force download.
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="'.str_ireplace(' ','_',basename($file)).'"');
header('Content-Transfer-Encoding: binary');
header('Connection: Keep-Alive');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
//If download is larger the 2GB, alls not lost
header('Content-Length: '.sprintf("%u", filesize($file)));
//Clean the buffer
ob_clean();
//Open a handle to the file
$handle = fopen($file, "rb");
$chunksize=(sprintf("%u", filesize($file))/$chunk);
set_time_limit(0);
//Loop through the file
while (!feof($handle)) {
//Echo a piece of the file out
echo fgets($handle, $chunksize);
flush();
}
fclose($handle);
die;
}else{return array('error'=>'Not found!');}
return;
}
?>
You would also need to check user permission on the file, but thats another question.
Related
I have html, pdf, doc files in a web folder. I have a php file that list out all the files in my folder. I am checking html files for login sessions. If logged in the html file is shown if not it will redirect to login prompt. How do I do this for PDF and doc file.
If I have direct URL for pdf or doc I can open the file. I would like to restrict it by checking the login session. Is this possible?
Something like if click www.mydomainexample.com/test.pdf - This should check login session and not open pdf automatically. Same way:
www.mydomainexample.com/test.doc - should check login session and not download doc file automatically.
E.g:
webserver root folder has the following files:
login.php
listoffiles.php
abc.html
cde.html
fgh.html
first.pdf
second.pdf
third.pdf
first.doc
second.doc
third.doc
All the html files have session check. How do I check login session for pdf and doc for the file structure.
Thanks!
Once user get logged in to your site set $_SESSION['user_id'] of logged in user and on doc url put this code
if(empty($_SESSION['user_id'])) {
// code to send user on login page
}
Not sure if you still need the answer, but one of the ways you can handle this is by using an .htaccess file if your using an Apache server. Put an .htaccess in the folder with the doc and pdf files. You can then use something like the code block below to deny access to those file types. It should give a 403 Forbidden error.
Order Allow,Deny
Allow from all
<Files ~ "\.(doc|pdf)$">
Deny from all
</Files>
Additionally, you can then setup a PHP script that lets you load the files through the script OR you can do some additional work with HTACCESS file that checks for HTTP Referrer header is from your domain before loading the file.
$filename = 'readme.pdf';
if (file_exists($filename)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="' . basename($filename) . '"');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($filename));
readfile($filename);
exit;
}
actually i was use this type but i had used tcpdf
and you can also set on this file use your PHP code and after you can set as download or displaying in browser.
it's very easy for making thousands pdf.
session_start();
//rest of your code and then...
if($_SERVER['REQUEST_METHOD'] == 'POST') {
enter code here
}
I don't actually now hoy to ask this question, so it may be probably repeated. Let's see: I would like to disable downloading a file from my web without a download script (just using the URL: http://something/file.zip) unless you're registered, with PHP preferably. Yes, it's a very common topic but I haven't found any information! A lot of pages do this, such as uploaded.net. I hope you understand what I'm talking about. Thanks!
First and foremost, don't allow direct access to the file. Store it outside of your web application's root folder, elsewhere on the file system, so that there is no link which can be used to download it. This is because direct access skips any PHP application and interacts only with the web server, which has no knowledge of your application's session values.
Then create a "download" script to serve the file to users. Generally such a script would be given some identifier for the file, something like:
http://yourserver.com/download.php?file=file.zip
(Important: Be very careful how you identify that file. Do not just blindly let users download whatever they want, or they can enter longer paths onto the URL and download any file from your server. Always validate access to things first.)
This would be just like any other PHP script, except that instead of displaying HTML it would return a file. The actual part of outputting the file can be as simple as:
readfile('/path/to/file.zip');
You'd also likely want to set content headers appropriately, etc. A more complete example can be found in the documentation:
<?php
$file = 'monkey.gif';
if (file_exists($file)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="'.basename($file).'"');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
readfile($file);
exit;
}
?>
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 9 years ago.
Improve this question
i am confused in how to allows download the file.zip after the payment.If i redirect them to a download page where is file is placed in sever they can download the file again easily or they can pass that link to anyone.
Any suggestions please!
Don't use a direct link to the file - use a PHP file that serves the file up as a download, but only if a certain session var is found (created in the confirmation of the payment process)
Just like #SmokeyPHP mentioned, just output the file through PHP instead of linking to it directly.
<?php
$file = 'monkey.gif';
if (file_exists($file)) {
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');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
ob_clean();
flush();
readfile($file);
exit;
}
?>
http://php.net/manual/en/function.readfile.php
This way you have a full control over who downloads what. Of course depending on the file size, you may wish to split the file into smaller chunks. You don't want to be buffering 40 MB files in your server memory every 5s. With bigger files, you can use something like this:
<?php
$file = fopen("file.dat", "r");
while (!feof($file)) {
echo fgets($file);
}
fclose($file);
?>
put .zip file outside the webserver;
protect the .zip URL with some rule [e.g. being logged in and having purchased the resource];
associate the .zip URL with an action that reads the actual binary file and forwards it to user [plenty of examples in here].
I made a form that allows user to upload a file (text documents). I’m using an unique (?) file name made from a combination of time() and the user id (only logged user can upload).
My problem is that the file cannot be accessed externally. That is, only the user who uploaded it or an admin can see it, while it can’t be reached while simply typing www.domain.com/uploads/file_name.txt
I know I can prevent the access to file through htaccess, but if I did understand it correctly, in that way I couldn’t open it even after I am logged in as admin (or as the user who sent the file).
I know I could open the file locally through php so I could show up the content through my admin panel, but that’s a pain since I could output only plain text files without problems. Also I could not download the file.
I could generate on the fly pdf or rtf versions in some cases, however that would quite a long way since I would need to elaborate the content in a complex way. And anyway, I would have no idea how to handle Word or OpenOffice files, which are likely to be the most common cases, and how to not loose formatting or other possible features.
Any ideas?
Why not display a download link for logged in users, like www.domain.com/download.php?file=... The code could look something like:
if( isset($_GET['file']) && user_is_logged_in() ) {
$file = DIR_SOME_WHERE .'/'. basename($_GET['file']);
if( file_exists($file) && user_has_file_access( $file ) ) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename($file));
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Content-Length: ' . filesize($file));
ob_clean();
flush();
readfile($file);
exit;
}
}
I have files stored outside the public_html folder for security purposes. However, I would like to link to specific files somehow where a user could download one of these files.
I am using a jquery script that allows me to specify a server PATH as an upload folder, and it does upload outside the public_html folder.
The only problem is it requires me to specify a URL to the "upload path" which is used to download the files. I thought I might be able to something like:
public_html/redirect (contains htaccess which forwards all requests to "hiding" folder)
hiding (outside public_html)
A user clicks /redirect/file.doc and they download a file located at hiding/file.doc
Is this possible? If not, how can I give specific file download access to files outside of my public_html directory? I know I've seen it done on other scripts before...
You can do this with "php download handler":
You can use method like this one to return file contents and file information headers to users browser, just make sure that nothing else is outputted before this.
I suggest that you put this to separate file and call that for example download.php.
function returnFile( $filename ) {
// Check if file exists, if it is not here return false:
if ( !file_exists( $filename )) return false;
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
// Suggest better filename for browser to use when saving file:
header('Content-Disposition: attachment; filename='.basename($filename));
header('Content-Transfer-Encoding: binary');
// Caching headers:
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
// This should be set:
header('Content-Length: ' . filesize($filename));
// Clean output buffer without sending it, alternatively you can do ob_end_clean(); to also turn off buffering.
ob_clean();
// And flush buffers, don't know actually why but php manual seems recommending it:
flush();
// Read file and output it's contents:
readfile( $filename );
// You need to exit after that or at least make sure that anything other is not echoed out:
exit;
}
Extending it for basic use:
// Added to download.php
if (isset($_GET['file'])) {
$filename = '/home/username/public_files/'.$_GET['file'];
returnFile( $filename );
}
Warning:
This is basic example and does not take into account that user may try to take some evil advantages of $_GET that is not properly sanitized.
This means basically that user can for example retrieve passwd file or some other sensitive information if certain conditions apply.
For example, retrieving /etc/passwd:
Just point browser to http://server.com/download.php?file=../../../etc/passwd and server returns that file. So before real use you should find out how to properly check and sanitize any user supplied arguments.
It is not possible to for paths outside the public_html.
mod_rewrite only rewrites the request, but the path still should be available to the users.
Another standard way to do this is using mod_xsendfile -- it will allow a web application to have the web server send a file as its output by specifying the path in a header (X-SendFile).