forcing a file to download [duplicate] - php

This question already has answers here:
php - How to force download of a file?
(7 answers)
Closed 7 years ago.
I have a php page with information, and links to files, such as pdf files. The file types can be anything, as they can be uploaded by a user.
I would like to know how to force a download for any type of file, without forcing a download of links to other pages linked from the site. I know it's possible to do this with headers, but I don't want to break the rest of my site.
All the links to other pages are done via Javascript, and the actual link is to #, so maybe this would be OK?
Should I just set
header('Content-Disposition: attachment;)
for the entire page?

You need to send these two header fields for the particular resources:
Content-Type: application/octet-stream
Content-Disposition: attachment
The Content-Disposition can additionally have a filename parameter.
You can do this either by using a PHP script that sends the files:
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment');
readfile($fileToSend);
exit;
And the filenames are passed to that script via URL. Or you use some web server features such as mod_rewrite to force the type:
RewriteEngine on
RewriteRule ^download/ - [L,T=application/octet-stream]

Slightly different style and ready to go :)
$file = 'folder/' . $name;
if (! file) {
die('file not found'); //Or do something
} else {
// Set headers
header("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-Disposition: attachment; filename=$file");
header("Content-Type: application/zip");
header("Content-Transfer-Encoding: binary");
// Read the file from disk
readfile($file);
}

Related

PHP Force Download [duplicate]

This question already has answers here:
Handle file download from ajax post
(21 answers)
Closed last year.
I am new to php and ajax. Im trying to force download a file from a list of documents. The functions below gets triggered using an ajax call after a button click.
function downloadDocument($filename) {
$file_path = ".........../DocUploader/Uploads/" . $filename;
if (file_exists($file_path)) {
header("Content-Description: File Transfer");
header("Content-Type: application/json");
header("Content-Disposition: attachment; filename=\'" . $filename);
readfile($file_path);
} else{
echo "Document does not exist";
}};
Instead of downloading the file, I assume I am getting the file content as a response. I would really appreciate any advise on what I should do.
First remove any echo's or output to the browser before sending any header, ie. remove the echo "File exists";
The file name should be encapsulated in quotations, ie. Content-Disposition: attachment; filename="filename.ext"
<?php
header("Content-Description: File Transfer");
header("Content-Type: application/json");
header('Content-Disposition: attachment; filename="'. $filename .'"');
readfile($file_path);
Keep in mind to set correct Content-type based on the real kind of the downloaded document, see topic What are all the possible values for HTTP "Content-Type" header?
You can dynamically detect the MIME type using PHP function mime_content_type()
And reference for PHP header.

Unable to force download file with PHP

I need to create a PHP page which starts automatically the download a file (I don't want to expose the Download link). I've tried with several examples on the web but all examples will end up with opening the file in the browser with the uncorrect content type.
For example:
<?php
// We'll be outputting a ZIP
header("Content-type: application/zip");
// Use Content-Disposition to force a save dialog.
// The file will be called "downloaded.zip"
header("Content-Disposition: attachment; filename=downloaded.zip");
readfile('downloaded.zip');
?>
When I execute this page, the output on the browser is:
After trying all possible variants of this example my idea is that the problem is with my hosting environment. Which variable should I check and maybe ask to be enabled to my provider ?
Thanks!
Try printing out the following variable using phpinfo(): SERVER["HTTP_ACCEPT_ENCODING"].
My suspect is that you don't have zip allowed- could be something different like "gzip" for example.
Here's the code I used back in the day: header ("Content-Type: application");
header ("Content-Disposition: attachment; filename=\"$file\"");
header ("Content-Length: " . filesize ('./FILES/' . $file));
header ("Cache-Control: no-cache");
header ("Pragma: no-cache");
readfile ('./FILES/' . $file);
Just modify the content-type header ofc.

Force user to download file in PHP [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Forcing to download a file using PHP
When we need to force user to download a file, we use header with several parameters/options. What if I use
header("location:test.xlsx");
This is working :) Is there any drawback of using this shortcut ?
This approach should solve the problems mentioned here
download.php?filename=test.xlsx
if isset ($_GET['filename']){
$filename = $_GET['filename']
}
else{
die();
}
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);
And of course don't forget to secure this so users can't download other files
There are a few disadvantages to this method:
If the file is one the browser can read, it won't be downloaded (like .txt, .pdf, .html, .jpg, .png, .gif and more), but simply be shown within the browser
Users get the direct link to the file. Quite often, you don't want this because they can give this link to others, so...
it will cost you more bandwidth
it can't be used for private files
if it's an image, they can hotlink to it
All you're doing is redirecting to a file. This is no different than if they went to it directly.
If you are trying to force a download, you need to set your Content-Disposition header appropriately.
header('Content-Disposition: attachment');
Note that you can't use this header when redirecting... this header must be sent with the file contents. See also: https://stackoverflow.com/a/3719029/362536
Not every file is forced to download.
If you were to use that header() on a .jpg the browser won't open the download dialog but will just show the image.

How to prevent file location from showing?

I am allowing users to upload documents to the server. However, i don't want them to obviously see where the files are being stored. What can i do that will allow them to still get the file but without seeing the file location.
You can use a PHP query to accomplish this, lets say you use the following URL:
http://mysite.com/files.php?file=xyz.pdf
In files.php you can check the get variable file and have a hard coded function that retrieves the file. You can do this many ways one by using headers to force a download or read the file into a var and print it's contents to the page. For say like a pdf reading the file and printing it to the page is the same as linking it to the file.
warning though: like with using headers do not print anything to the page except the file. I also recommend declairing you headers still if you read the file and print it so that the end user will not get the gobbly goop that is the source of the file i.e. jpg or pdf.
Oh no, I forgot a header warning, I have been running into a header problem ever since Adobe made the ISO for PDF's open source, depending on the application that produced the PDF and the browser from which the user is uploading the PDF from, the header will be anything from:
'application/pdf', 'application/x-download','application/octet-stream','application/octet','binary/octet-stream'
so be careful hard coding the upload section to a header type, I know this question is about downloads but i just thought i would throw that in there. Also using headers for downloads doesn't matter I would simply use the standard application/pdf there.
There are a few ways todo this but i prefer using .htaccess
So my link would look like http://example.com/files/filename.zip
extra parameters within the url could be used a username or password like:
http://example.com/files/bob/filename.zip
http://example.com/files/18d52c/filename.zip
Then thos could be checked against a database to see if user is allowed to download that specific file, much like you would use for instant downloads after payment.. but a basic method would be like so:
.htaccess
RewriteRule ^files/(.*)$ serve.php?file=$1
serve.php
<?php
if(isset($_GET['file'])){
$file=basename($_GET['file']);
//Protect the index.php && serve.php
if(basename($_GET['file'])=='index.php' || basename($_GET['file'])=='serve.php'){
header("HTTP/1.1 403 Forbidden");die();
}
$downloadFolder="original_location/";
if(file_exists($downloadFolder.$file)){
$fsize = filesize($downloadFolder.$file);
$ctype=finfo_file(finfo_open(FILEINFO_MIME_TYPE), $downloadFolder.$file);
if(ini_get('zlib.output_compression'))
ini_set('zlib.output_compression', 'Off');
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: private",false);
if(strstr($_SERVER["HTTP_USER_AGENT"],"MSIE")==false) {
header("Content-Type: application/force-download");
header('Content-Description: File Transfer');
}else{
header("Content-Type: $ctype");
}
header("Content-Disposition: attachment; filename=\"".basename($file)."\";" );
header("Content-Transfer-Encoding: binary");
header("Content-Length: ".$fsize);
ob_clean();
flush();
readfile('original_location/'.$file);
}else{
header("HTTP/1.0 404 Not Found");
}
die();
}
header("HTTP/1.0 404 Not Found");
?>
original_location/index.php
header("HTTP/1.1 403 Forbidden");
Store it using some random unique ID that you can map to the real file, then serve it using a script that does readfile() on the actual file.
The http://php.net/readfile docs also have an example on how to force it being a download.

Illustrator opening as PDF

I am coding a file sharing application for my office. One strange problem I am going through is the Illustrator files being opened in PDF when you hit the download button.
This problem is triggered because the mime type of illustrator files is application/pdf. So the browser when it reads the file, triggers Acrobat to open the file. Is there any way I could instruct the browser to open the file in Illustrator?
Or is there any way to modify the mime type after uploading the file? The backend code is PHP.
Thank you for any help.
One way to do this is to force the browser to display the "download file"-dialog. So the user can decide what to do with the file.
This can be done via PHP-Headers. (http://www.php.net/manual/en/function.header.php#83384)
There is also an example on how to this (Post 83384):
<?php
// downloading a file
$filename = $_GET['path'];
// fix for IE catching or PHP bug issue
header("Pragma: public");
header("Expires: 0"); // set expiration time
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
// browser must download file from server instead of cache
// force download dialog
header("Content-Type: application/force-download");
header("Content-Type: application/octet-stream");
header("Content-Type: application/download");
// use the Content-Disposition header to supply a recommended filename and
// force the browser to display the save dialog.
header("Content-Disposition: attachment; filename=".basename($filename).";");
/*
The Content-transfer-encoding header should be binary, since the file will be read
directly from the disk and the raw bytes passed to the downloading computer.
The Content-length header is useful to set for downloads. The browser will be able to
show a progress meter as a file downloads. The content-lenght can be determines by
filesize function returns the size of a file.
*/
header("Content-Transfer-Encoding: binary");
header("Content-Length: ".filesize($filename));
#readfile($filename);
exit(0);
?>
When using this example please consider that using
$filename = $_GET['path'];
is a big security problem. You should work with something like ID's instead or validate the input.
For example:
if($_GET['file'] == 1) {
$filename = foobar.pdf;
} elseif($_GET['file'] == 2) {
$filename = foo.pdf;
} else {
die();
}

Categories