PHP: How to make browser to download file on click - php

PHP Beginner. File uploading is successful but my browser doesn't download the files, instead it reads the file. So i referred other threads and found below code which is not working. I want to download files when i click on the hyperlink download. Selected the path from MySQL database.
$rows = mysqli_num_rows($result);
if($rows>0)
{
while($row = mysqli_fetch_assoc($result))
{
?>
<div> <?php echo $row['Object_Name'];?>
<a href="<?php
$file_url = $row['Object_Path'];
header('Content-Type: application/octet-stream');
header("Content-disposition: attachment; filename=\"".$row['Object_Name']. "\"");
readfile($file_url);
?>">Download</a><br>
</div>
<?php
}
}

In a paged called download.php, have the following code:
<?php
$filename = 'file.pdf';//this should be the name of the file you want to download
header('Pragma: public');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Cache-Control: private', false); // required for certain browsers
header('Content-Type: application/pdf');
header('Content-Disposition: attachment; filename="'. basename($filename) . '";');
header('Content-Transfer-Encoding: binary');
header('Content-Length: ' . filesize($filename));
readfile($filename);
exit;
?>
Your main page should then have a link to the download page like this:
DOWNLOAD
Let me know if that works for you.
Edited:
My previous example was for the download of a pdf file. In the case that you want to download a different type of file, a few lines have to be slightly modified. I recommend you first try downloading a pdf file with the previous code, and after having accomplished that testing out on other files.
To retrieve the path from the database, you can use MySQL (PDO).
$sqlStatement = "SELECT path FROM my_table WHERE some_id = ".$something;
/*if you are retrieving the path from the database,
you probably have a lot of different paths available
there, so only you know the criteria which will decide
which of the many paths it is that you choose to extract*/
$sqlPrepared = $connection->prepare($sqlStatement);
$sqlPrepared->execute();
$row_info = fetch($sqlPrepared);
$filename = $row_info['path'];// this would be the $filename = 'file.pdf'
//that was in the example above
If you are not sure how to connect to the database, there are a lot of articles online explaining MySQL that is relatively straightforward.
I hope that helped :)

You have to use two separate files.
In link page, you can output a HTML like this:
Download file 1
Download file 2
Download file 3
(...)
You can use a <form>, if you prefer.
Then, in download.php:
Select appropriate file using GET/POST parameter ($_GET['file'] in above example);
send appropriate headers (like in your original code);
echo your file (you can use readfile);
Mandatory: no additional output in this script! Even a single additional space will corrupt downloaded file.

Related

PHP - Forcing an MP3 file download

So, I need a little help here. I have a site which hosts some mp3s. When users click on the download url, it links directly to a file called downloadmp3.php, which goes 2 parameters in the url...the php file is included below, and it's basically supposed to FORCE the user to save the mp3. (not play it in the browser or anything).
That doesnt happen. Instead, it seems like the file is WRITTEN out in ascii to the browser. It seems like it's the actual mp3 file written out.
Here is my downloadmp3.php file...please, what's wrong in this code.
It works on my local LAMP (Bitnami Wampstack on windows)....that is, on my local testing environment, it sends the file to my broswer, and I can save it. When I upload it to the real server, it basically writes out the mp3 file.
Here is the culprit file, downloadmp3.php...please help
<?php
include 'ngp.php';
$file = $_GET['songurl'];
$songid = $_GET['songid'];
increasedownloadcount($songid);
if (file_exists($file)) {
header('Content-Description: File Transfer');
header('Content-Type: audio/mpeg');
header('Content-Disposition: attachment; filename=' . basename($file));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
ob_clean();
flush();
readfile($file);
exit;
}
?>
By the way, this site only hosts mp3s - no other audio or file format. So, this downloadmp3.php script should ideally ask the user where they want to save this file.
Thanks for your help in advance.
I think the filename should be in quotes:
header('Content-Disposition: attachment; filename="' . basename($file) . '"');
Change the content-type value to text/plain. With this browser wont recognize it and wont play the file. Instead it will download the file at clients machine.
Seems there is too many headers. I am sure they do SOMETHING... but this code works.
This code works with MP3 files.... downloads to a file. Plays without a problem.
if(isset($_GET['file'])){
$file = $_GET['file'];
header('Content-type: audio/mpeg');
header('Content-Disposition: attachment; filename=".$file.'"');
readfile('path/to/your/'.$file);
exit();
}
You can access it with ajax call, or this:
<a id="dl_link" href="download.php?file=<>file-you-wish-to-download<>" target="_blank">Download this file</a>
Hopefully this is of some use

Authorising users to view files PHP

I have a login system that is fully functional and I keep the user logged in by their ID in a Session Variable $_SESSION['user_id'].
I would like to use that ID to authorise them to view certain files.
I know I can use a MySQL database to store whether they are authorised to see a certain file and then check their ID against the database when it is accessed via a web page, e.g. file.php with a container on the page, however how do I stop someone from finding out what the URL of the file is (e.g. /files/file.pdf) and navigating to that in their browser and viewing it that way?
I know there has to be a way but my knowledge is obviously limited.
Any help would be appreciated.
Thank you
Connor Wyatt
As per OP's request.
Place your files outside the public html area.
$file = "/var/user/you/outside_folder/file.xxx"; type of thing.
"you can use readfile from your script if the user is authorized"
Bansi's suggestion of using readfile is a good method.
As per an example on that page:
$filename = "file.csv";
$filepath = "/path/to/file/" . $filename;
From example #1
<?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;
}
?>
where $file = 'monkey.gif'; can be modified to read as:
$file = '/var/user/you/outside_folder/monkey.gif';

Can I download .php file from http://www.example.com/example.php

I have created a file download system with php. I created like that
phpfiledownload.php
--------------------
<?php
$file = 'testing.php';
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, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
ob_clean();
flush();
readfile($file);
exit;
} ?>
And I also created testing.php file like the following
testing.php
------------
<?php echo "Hello World"; ?>
When I run phpfiledownload.php form my localhost I got testing.php file.
But when I change testing.php to http://www.anotherdomain.com/example.php in phpfiledownload.php I can't download http://www.anotherdomain.com/example.php.
So, how I can got http://www.anotherdomain.com/example.php via my phpfiledownload.php
To download http://www.example.com/example.php you can use the code below
file_put_contents("example.php", fopen("http://www.example.com/example.php", 'r'));
Note: If example.php contains php code it will run on the webserver and return the HTML output to you. So your file be the output of example.php and not the source code.
Tip
A URL can be used as a filename with this function if the fopen
wrappers have been enabled. See fopen() for more details on how to
specify the filename. See the Supported Protocols and Wrappers for
links to information about what abilities the various wrappers have,
notes on their usage, and information on any predefined variables they
may provide.
Taken from PHP Manual, here.
Your question is not very clear: are you meaning to download the php file or the result processed by the web server?
In your code, "testing.php" is a local file, while "http://www.example.com/example.php" is an URL.
In the first case your local web server fetches the local file and return it using the appropriate headers.
In the second case you obtain only the html output produced by the web server of the site "http://www.example.com"

The code is for downloading excel file(.xls)

Problem:
After download, the file doesn't contain the data.
i.e it become blank.
So please help me for this.
<?php
session_start();
include_once 'oesdb.php';
$id=$_REQUEST['id'];
if(isset($_REQUEST['id']))
{
$sql=executeQuery("SELECT * FROM file where id=$id");
$rows = mysql_fetch_array($sql);
$file =$rows['file'];
header('Content-Description: File Transfer');
header('Content-Type: application/vnd.ms-excel');
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('uploads/'.$file);
exit;
}
?>
Why not create a HTACCESS file in uploads folder then states
Allow From 127.0.0.1
Deny From All
Then just create a URL, use HTML5's new download feature, do something like this:
click to download
It saves time trying to use PHP to make a download script.
try replacing this:
$file =$rows['file'];
by this:
$file = "uploads/".$rows['file'];
and this:
readfile('uploads/'.$file);
by this
readfile($file);
if still not working put the value returned by the readfile function
IMPORTANT
Please take in consideration the sql injection issues (see comment of Ondřej Mirtes)
The problem is here:
header('Content-Length: ' . filesize($file));
Content-Length receives zero value and browser downloads zero-length file, as you told him. If $file is path relative to upload/, you should do this:
header('Content-Length: ' . filesize('upload/'.$file));
Be sure that filezise() returns correct size and readfile() realy outputs it.
But the other problem is that you mentioned UPLOAD folder and using uploads. They are not same and case is important. Also, may be using relative paths in 'uploads/'.$file is not a good idea, it is better to use absolute path. For example, '/var/www/upload/'.$file.

Creating a download link for .jpg file using PHP

This one should be easy, I think. I have a paginated image gallery, and under each image is a small link that says "Download Comp". This should allow people to quickly download the .jpg file (with a PHP generated watermark) to their computer.
Now, I know I can just link straight to the .jpg file, but that requires the user to have the image open in a new window, right click, Save As..., etc. Instead, I want the "Download Comp" link to initiate the download of the file immediately.
PHP.net seemed to suggest using readfile(), so each "Download Comp" link is being echoed as "?download=true&g={$gallery}&i={$image}".
Then at the top of the page I catch to see if the $_GET['download'] var isset, and if so, I run the following code:
if(isset($_GET['download'])) {
$gallery = $_GET['g'];
$image = $_GET['i'];
$file = "../watermark.php?src={$gallery}/images/{$image}";
header('Content-Description: File Transfer');
header('Content-Type: application/jpeg');
header('Content-Disposition: attachment; filename='.basename($file));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: public');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
ob_clean();
flush();
readfile($file);
}
The link takes a lonnnnnnnnng time, and then it brings up a dialog prompt asking you to Open or Save the file, but once you Save and try to open it, it says the file is corrupt and can't be opened.
Any ideas?
Don't set $file to a relative url. The readfile function will try to access the php file on the server. That is not what you want. In your case it looks like the watermark.php file will send the contents you want, so you could possibly just set up the environment it needs and include it.
<?php
if(isset($_GET['download'])) {
$gallery = $_GET['g'];
$image = $_GET['i'];
$_GET['src'] = "{$gallery}/images/{$image}";
header('Content-Description: File Transfer');
header('Content-Type: image/jpeg');
header('Content-Disposition: attachment; filename='.basename($image));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: public');
header('Pragma: public');
ob_clean();
include('../watermark.php');
exit;
}
Another (simpler) way is to modify watermark.php. Add a query parameter to make it send the proper headers to force a download and link to that
...
watermark.php:
<?php
if (isset($_GET['download']) && $_GET['download'] == 'true') {
header('Content-Description: File Transfer');
header('Content-Type: image/jpeg');
header('Content-Disposition: attachment; filename='.basename($src));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: public');
header('Pragma: public');
}
// continue with the rest of the file as-is
Also, you don't need the call to flush(). There should not be any output to send at that point, so it is not necessary.
header('Content-Type: image/jpeg');
Perhaps?
I think you might need to follow the call to readfile() with a call to exit() to make sure nothing else gets written to the output buffer.
This seems like a security issue.
What if someone enters:
$g = '../../../../../../';
$i = '../../sensitive file at root';
How about making .htaccess (if you are using apache) i for the gallery directory serve jpegs up as a download rather than normal.
Also, try file_get_contents() instead of readfile(). I find it works under more circumstances. I would also recommend you use ob_flush() after you output the image data. I've never needed to use ob_clean() or flush() to get this kind of thing to work.
And as Eric said, you may also want to put a call to exit() in there as well for good measure if it still isn't working just in case you are getting some junk data stuck at the end.

Categories