I'm really struggling to get my application to open a pdf when the user clicks on a link.
So far the anchor tag redirects to a page which sends headers that are:
$filename='./pdf/jobs/pdffile.pdf;
$url_download = BASE_URL . RELATIVE_PATH . $filename;
header("Content-type:application/pdf");
header("Content-Disposition:inline;filename='$filename");
readfile("downloaded.pdf");
this doesn't seem to work, has anybody successfully sorted this problem in the past?
Example 2 on w3schools shows what you are trying to achieve.
<?php
header("Content-type:application/pdf");
// It will be called downloaded.pdf
header("Content-Disposition:attachment;filename=\"downloaded.pdf\"");
// The PDF source is in original.pdf
readfile("original.pdf");
?>
Also remember that,
It is important to notice that header() must be called before any
actual output is sent (In PHP 4 and later, you can use output
buffering to solve this problem)
$name = 'file.pdf';
//file_get_contents is standard function
$content = file_get_contents($name);
header('Content-Type: application/pdf');
header('Content-Length: '.strlen( $content ));
header('Content-disposition: inline; filename="' . $name . '"');
header('Cache-Control: public, must-revalidate, max-age=0');
header('Pragma: public');
header('Expires: Sat, 26 Jul 1997 05:00:00 GMT');
header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT');
echo $content;
There are some things to be considered in your code.
First, write those headers correctly. You will never see any server sending Content-type:application/pdf, the header is Content-Type: application/pdf, spaced, with capitalized first letters etc.
The file name in Content-Disposition is the file name only, not the full path to it, and altrough I don't know if its mandatory or not, this name comes wrapped in " not '. Also, your last ' is missing.
Content-Disposition: inline implies the file should be displayed, not downloaded. Use attachment instead.
In addition, make the file extension in upper case to make it compatible with some mobile devices. (Update: Pretty sure only Blackberries had this problem, but the world moved on from those so this may be no longer a concern)
All that being said, your code should look more like this:
<?php
$filename = './pdf/jobs/pdffile.pdf';
$fileinfo = pathinfo($filename);
$sendname = $fileinfo['filename'] . '.' . strtoupper($fileinfo['extension']);
header('Content-Type: application/pdf');
header("Content-Disposition: attachment; filename=\"$sendname\"");
header('Content-Length: ' . filesize($filename));
readfile($filename);
Technically Content-Length is optional but it is important if you want the user to be able to keep track of the download progress, and detect if the download was interrupted before the end. When using it you have to make sure you won't be send anything along with the file data. Make sure there is absolutely nothing before <?php or after ?>, not even an empty line.
I had the same problem recently and this helped me:
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, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . filesize("PATH/TO/FILE"));
ob_clean();
flush();
readfile(PATH/TO/FILE);
exit();
I found this answer here
Can you try this, readfile need the full file path.
$filename='/pdf/jobs/pdffile.pdf';
$url_download = BASE_URL . RELATIVE_PATH . $filename;
//header("Content-type:application/pdf");
header("Content-type: application/octet-stream");
header("Content-Disposition:inline;filename='".basename($filename)."'");
header('Content-Length: ' . filesize($filename));
header("Cache-control: private"); //use this to open files directly
readfile($filename);
You need to define the size of file...
header('Content-Length: ' . filesize($file));
And this line is wrong:
header("Content-Disposition:inline;filename='$filename");
You messed up quotas.
header("Content-type:application/pdf");
// It will be called downloaded.pdf thats mean define file name would be show
header("Content-Disposition:attachment;filename= $fileName ");
// The PDF source is in original.pdf
readfile($file_url);
Related
A friend of mine configured h2ml2canvas for me as I don't understand javascript. When saving using h2ml2canvas it generates a random filename e.g.
df0e604b2962492165eb8f2b31578171
Is there a way to specify a filename prefix? e.g. soccer then generate a random 3-4 digit number? Alternatively is there a way to open a save as dialogue instead of downloading an image on click? My download.php file.
<?php
$file = trim($_GET['path']);
// force user to download the image
if (file_exists($file)) {
header('Content-Description: File Transfer');
header('Content-Type: image/png');
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);
unlink($file);
exit;
}
else {
echo "error not found";
}
?>
The filename in your case is actually generated (or not) by the PHP server-side, not the JavaScript you've quoted. When it returns the data to send back, it's including a Content-Disposition header, probably one that looks like this:
Content-Disposition: attachment
It's possible to suggest a filename to the browser by adding to that header:
Content-Disposition: attachment; filename=soccer123.xyz
In the PHP somewhere, you should find:
header("Content-Disposition", "attachment");
or similar. You can change it to:
header("Content-Disposition", "attachment; filename=soccer-" . rand(100,999) . ".xyz");
(Probably best to make the .xyz an appropriate extension for the type of image, e.g. .png or .jpg...)
Re your edit, you can replace:
header('Content-Disposition: attachment; filename='.basename($file));
with
header('Content-Disposition: attachment; filename=soccer-'.rand(100,999).'.xyz');
again you'll want a correct extension instead of .xyz.
I am just a beginner with PHP. I am trying to download an image file when a url is clicked.
When I hardcode the filename it works, however when I try to download different image files based on the url clicked, it does not work. The code might explain it in a better way.
Code when a url is clicked
Download brochure
download.php
<?php
$var=$_GET['var'];
$filename=$var;
$filename = './img/Photo6.jpg'; // this works
//$filename = $var; // this does not work
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: image/jpeg');
header('Content-Disposition: attachment; filename="'. basename($filename) . '";');
header('Content-Transfer-Encoding: binary');
header('Content-Length: ' . filesize($filename));
readfile($filename);
exit;
?>
Kindly help.
Thanks.
when you use:
$_GET['var'];
You are expecting a url construct with an ? inside it:
./download.php?var=./img/Photo6.jpg
in your sample: var=./img/Photo6.jpg, tells to php the variable GET[var] will take the value ./img/Photo6.jpg
so, your different image files based on the url clicked, must have the
./download.php?var=XXX
structure to work. Be sure all your urls has that structure.
Hello I am trying to generate a php powered download link for my program, I had copied and pasted some old code I had laying around which worked in the past, and it still seems to work okay except for 2 issues.
Issue 1: No matter what it always download the file as link.php not the filename
Issue 2:The filesize isn't sent to the browser(not really that concerned about this)
Mainly I need to know what I am doing wrong in setting the filename, here is my code below:
$file = $_GET['file'].'.exe';
if ($_GET['DL'] == "GO") {
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/octet-stream');
header('Content-Disposition: attachment; filename="'. basename('MIRROR/'.$file) . '";');
header('Content-Transfer-Encoding: binary');
header('Content-Length: ' . filesize('MIRROR/'.$file));
ob_clean();
flush();
readfile('MIRROR/'.$file);
die();
}
Try taking out the trailing ;:
header('Content-Disposition: [..snip...] . basename($file) . '";');
^--- here
i though i found the answer here:
Serving .docx files through Php
But i am still getting the error that the file is corrupt when trying to download and open a docx server via php
Maybe you can see something wrong with my code. The .doc works fine it is the docx that fail.
$parts = pathinfo($doc);
$docFile = $userDocRoot.$doc;
if ( !file_exists($docFile) ){
throw new Exception("Can not find ".$parts ['basename']." on server");
}
if ( $parts['extension'] == 'docx' ){
header('Content-type: application/vnd.openxmlformats- officedocument.wordprocessingml.document');
header('Content-Disposition: attachment; filename="'.$parts['basename'].'"');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
ob_clean();
flush();
readfile($docFile);
}else{
header('Content-type: application/msword');
header('Content-Disposition: attachment; filename="'.$parts['basename'].'"');
readfile($docFile);
}
The solution for me was to add
$fsize = filesize($docFile);
header("Content-Length: ".$fsize);
Thanks for everyones help
There were a few extra spaces in your code which would cause it to fail.
Try using this code:
$parts = pathinfo($doc);
$docFile = $userDocRoot . $doc;
if(!file_exists($docFile)){
throw new Exception('Can not find ' . $parts['basename'] . ' on server');
}
if($parts['extension'] == 'docx') {
header('Content-type: application/vnd.openxmlformats-officedocument.wordprocessingml.document');
header('Content-Disposition: attachment; filename="' . $parts['basename'] . '"');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
ob_clean();
flush();
readfile($docFile);
} else {
header('Content-type: application/msword');
header('Content-Disposition: attachment; filename="' . $parts['basename'] . '"');
readfile($docFile);
}
If it still doesn't work, try commenting out the header and the readfile lines, then you will see if there are any errors.
Also, I suggest that you check the filenames against a whitelist, so that people can't download PHP files with passwords in them, etc.
I have just spent a while looking at why my DOCX files are being corrupted and stumbled across this... but I have also found the answer elsewhere...
$fsize = filesize($docFile);
header("Content-Length: ".$fsize);
This gave me the tools to look for... and the key is that filesize() needs the basename of the file to get an accurate file size!
Adapting my code:
header("Content-Length: ".filesize(basename($file)));
This now offers DOCX (I have set the Content-type to "application/vnd.openxmlformats-officedocument.wordprocessingml.document") as intended and I do not have to "repair" the document like others have reported... (I also found that repairing worked)
Here is a code that's working for me (after about 5 hours of messing around):
// headers to send your file
header('Content-Type: application/vnd.openxmlformats-officedocument.wordprocessingml.document');
header("Content-Length: " . filesize($original_file));
header('Content-Disposition: attachment; filename="' . $new_filename . '"');
ob_clean();
flush();
readfile($original_file);
exit;
I hope it helps :)
I had the same issue.
The reason was, that somewhere in my php-file two spaces were hidden.
Removing them fixed the issue.
Add "//" in front of the header and readfile-statements
Write echo "test"; after the readfile-statement.
Then look in the HTML source-code, if there are spaces in front of
the "test".
I'm trying to make a file that send a pdf file to the visitor.
I have file: download.php
and this is his content:
header('Content-disposition: attachment; filename='.$_GET['file']);
header('Content-type: application/pdf');
readfile($_GET['file']);
for some reason, the file sending an empty pdf file 183 bytes.
any advice?
thanks.
You should provide the full path to the file for readfile() not just a filename.
First off, you really should first check if the file exists with file_exists
Second ... this seems pretty insecure since you allow specifying the filename through a global $_GET parameter. What if I would try to download your config file like download.php?file=../application/settings/config.ini? You should first filter the $_GET parameter and make sure the file specified is allowed for being downloaded.
Try this:
header('Pragma: public'); // required
header('Expires: 0'); // no cache
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Cache-Control: private', false);
header('Content-Type: application/pdf');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s', filemtime($filepath)) . ' GMT');
header('Content-disposition: attachment; filename=' . $pathinfo['filename'] . '.pdf');
header("Content-Transfer-Encoding: binary");
header('Content-Length: ' . filesize($filepath)); // provide file size
header('Connection: close');
readfile($filepath);
exit();