I've got a php file downloader that I've been using to download a word document, now I need to allow it to download pdfs and it won't open the document stating that the pdf is corrupted.
I've looked up the content-type, ect and t appears to be correct for pdfs, however, I'm unsure of what else it could be. Am I missing some more headers that are necessary for downloading pdfs? I'm very new to this so I'm uncertain of all the possible problems.
my code:
if ($fd = fopen ($fullPath, "r")) {
$fsize = filesize($fullPath);
$path_parts = pathinfo($fullPath);
$ext = strtolower($path_parts["extension"]);
switch ($ext) {
case "pdf":
header("Content-Type: application/pdf");
header("Content-Disposition: attachment; filename=\"".$path_parts["basename"]."\"");
break;
case "docx":
header('Content-Type: application/vnd.openxmlformats-officedocument.wordprocessingml.document');
header("Content-Disposition: filename=\"".$path_parts["basename"]."\"");
break;
default;
header("Content-type: application/octet-stream");
header("Content-Disposition: filename=\"".$path_parts["basename"]."\"");
break;
}
<?php
header("Content-Type: application/pdf");
header("Content-Type: application/x-download");
header('Content-disposition: attachment; filename="test.pdf"');
header('Content-length: ' . filesize('test.pdf'));
readfile('test.pdf');
This works for me every time. You can try it.
Related
I am working on existing products and i am trying to resolve problem with downloading xlsx file.
When i download file through file manager, file is allright. But when i download file through Yii app, the file is corrupted.
Here is my code
public function actionCallLog($hash, $filename)
{
var_dump(
$hash, $filename
);
ignore_user_abort(true);
set_time_limit(0);
$path = "/var/www/html/uploads/call_log/".$hash.'/';
$dl_file= basename($filename).'.xlsx';
if (!file_exists($path.$dl_file)) {
$dl_file= basename($filename).'.csv';
}
$fullPath = $path.$dl_file;
if ($fd = fopen ($fullPath, "r"))
{
$fsize = filesize($fullPath);
$path_parts = pathinfo($fullPath);
$ext = strtolower($path_parts["extension"]);
switch ($ext)
{
case "xlsx":
header('Content-Description: File Transfer');
header("Content-type: application/xlsx");
header("Content-Disposition: attachment; filename=\"".$path_parts["basename"]."\"");
break;
case "csv":
header('Content-Description: File Transfer');
header("Content-type: application/csv");
header("Content-Disposition: attachment; filename=\"".$path_parts["basename"]."\"");
break;
// add more headers for other content types here
default;
header('Content-Description: File Transfer');
header("Content-type: application/octet-stream");
header("Content-Disposition: filename=\"".$path_parts["basename"]."\"");
break;
}
header("Content-length: $fsize");
header("Cache-control: private");
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Expires: 0');
header('Pragma: public');
while(!feof($fd))
{
$buffer = fread($fd, 2048);
echo $buffer;
}
}
fclose ($fd);
exit;
}
Does anybody know where can be the problem?
Thanks
Try turning off all the header instructions (and also the "echo $buffer;" as that might be a lot on screen) and see if any warnings or errors is printed on screen when opening the url for the file download.
If the corrupted file has a size, your code might actually give a warning or generate other output which will become part of the file because it is also echo'ed. Obviously that extra plain text output by your code would turn your correct xlsx into a corrupt file. You might be able to get that text by opening your corrupted file in a text-editor as it would show in there in plain text (probably at the start).
try add the response format
\Yii::$app->response->format = \yii\web\Response::FORMAT_RAW;
and for xlsx the content type should be
'application/vnd.ms-excel'
I want to create a download link, and I found an example online. I forget where I get it.
Here is the code:
<?php
// place this code inside a php file and call it f.e. "download.php"
//$path = $_SERVER['DOCUMENT_ROOT']."/path2file/"; // change the path to fit your websites document structure
$path = "music/";
$fullPath = $path.$_GET['download_file'];
if ($fd = fopen ($fullPath, "r")) {
$fsize = filesize($fullPath);
$path_parts = pathinfo($fullPath);
$ext = strtolower($path_parts["extension"]);
switch ($ext) {
//case "pdf":
//header("Content-type: application/pdf"); // add here more headers for diff. extensions
//header("Content-Disposition: attachment; filename=\"".$path_parts["basename"]."\""); // use 'attachment' to force a download
//break;
case "mp3":
header("Content-type: audio/mpeg"); // add here more headers for diff. extensions
header("Content-Disposition: attachment; filename=\"".$path_parts["basename"]."\""); // use 'attachment' to force a download
break;
case "wma":
header("Content-type: audio/wma"); // add here more headers for diff. extensions
header("Content-Disposition: attachment; filename=\"".$path_parts["basename"]."\""); // use 'attachment' to force a download
break;
case "ogg":
header("Content-type: audio/ogg"); // add here more headers for diff. extensions
header("Content-Disposition: attachment; filename=\"".$path_parts["basename"]."\""); // use 'attachment' to force a download
break;
default:
header("Content-type: application/octet-stream");
header("Content-Disposition: filename=\"".$path_parts["basename"]."\"");
}
header("Content-length: $fsize");
header("Cache-control: private"); //use this to open files directly
while(!feof($fd)) {
$buffer = fread($fd, 2048);
echo $buffer;
}
fclose ($fd);
}
exit;
// example: place this kind of link into the document where the file download is offered:
// Download here
?>
The problem is when I click the download link, it works. But after few seconds, my whole computer freezes and I need to force a shutdown.
What is the cause of this problem? Is it my computer fault or the code? I am using WAMP Server 2.
Update :
I tried to use readfile() instead of fread(), however I still get the same problem. Below is my code :
<?php
$directory_load = simplexml_load_file('conf/configuration.xml');
$path = $_SERVER['SERVER_ROOT'].$directory_load -> directories;
echo $path;
if($_GET['download_file'] != NULL) {
$fullPath = $path.$_GET['download_file'];
if (file_exists($fullPath)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename($fullPath));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($fullPath));
ob_clean();
flush();
readfile($fullPath);
exit;
}
else {
echo "<span style=\"font-size: 15px;\">The file you requested to download <span style=\"font-size: 30px; font-weight: bold; color: red; padding: 0px 20px;\">".$_GET['download_file']."</span> does not exists.</span>";
}
}
else {
header("location: index.php");
}
?>
UPDATE 2 :
I tested the code with Mozilla version 21.0, it works fine. But as I stated, my computer freeze when I click the download link, it is when I am using Coolnovo (ChromePlus) Version 2.0.8.33. Is it related to the browser?
Try clearing the buffer and flushing headers. See example below:
header("Content-type: text/csv");
header("Cache-Control: no-store, no-cache");
header('Content-Disposition: attachment; filename="' . $download_info->original . '"');
ob_clean(); // discard any data in the output buffer (if possible)
flush(); // flush headers (if possible)
readfile($path . $download_info->renamed);
SureVerify - Email Verification
I moved my application from a WAMP server (PHP version <= 5.2, Windows XP) to a LAMP server (PHP > 5.3, Ubuntu 12.04 LTS), and the problem that I have now is that my download function outputs the file on the screen and it's not forcing the browser to perform a download.
Anyone can point me in the right direction?
Here's the code:
function download()
{
$fullPath = $_POST['fisier'];
if($fullPath=="NULL")
{
echo "Wrong path!";
}
else
{
$fd = fopen ($fullPath, "r");
if ($fd) {
$fsize = filesize($fullPath);
$path_parts = pathinfo($fullPath);
$ext = strtolower($path_parts["extension"]);
switch ($ext) {
case "pdf":
header("Content-type: application/pdf");
break;
case "tiff":
header("Content-type: image/tiff");
break;
case "tif":
header("Content-type: image/tiff" );
break;
default:
header("Content-type: application/force-download");
break;
}
header("Content-Description: File Transfer");
header('Content-Disposition: attachment; filename="'.$path_parts["basename"].'"');
header("Content-length: ".$fsize);
header("Cache-control: private"); //use this to open files directly
ob_clean();
flush();
while(!feof($fd)) {
$buffer = fread($fd, 2048);
echo $buffer;
}
}
fclose ($fd);
exit;
}
}
You can use the Content-Disposition header as per the PHP docs:
If you want the user to be prompted to save the data you are sending,
such as a generated PDF file, you can use the ยป Content-Disposition
header to supply a recommended filename and force the browser to
display the save dialog.
// It will be called downloaded.pdf
header('Content-Disposition: attachment; filename="downloaded.pdf"');
try using header("Content-type: application/octet-stream"); instead of header("Content-type: application/force-download");
The recommended action for an implementation that receives an
"application/octet-stream" entity is to simply offer to put the data
in a file
From here. Looks like your application/force-download is non standard.
I have written a code to download pdf file from server, but the code is not working and I cant even see the errors
This is the code which I am using.
// place this code inside a php file and call it f.e. "download.php"
$path = $_SERVER['DOCUMENT_ROOT']."/product_images/"; // change the path to fit your websites document structure
fullPath = $path.$_REQUEST['download_file'];
if ($fd = fopen ($fullPath, "r")) {
$fsize = filesize($fullPath);
$path_parts = pathinfo($fullPath);
$ext = strtolower($path_parts["extension"]);
switch ($ext) {
case "pdf":
header("Content-type: application/pdf"); // add here more headers for diff. extensions
header("Content-Disposition: attachment; filename=\"".$path_parts["basename"]."\""); // use 'attachment' to force a download
break;
default;
header("Content-type: application/octet-stream");
header("Content-Disposition: filename=\"".$path_parts["basename"]."\"");
}
header("Content-length: $fsize");
header("Cache-control: private"); //use this to open files directly
while(!feof($fd)) {
$buffer = fread($fd, 2048);
echo $buffer;
}
}
fclose ($fd);
exit;
// example: place this kind of link into the document where the file download is offered:
// Download here
?>
I am fetching the file from database and this is my download link which I am using on my site
<div style="padding-left:320px; padding-top:5px;"><a href="<?php echo URL ?>download.php?download_file=<?php echo $prod_details['specification_pdf']?>">
<img src="<?php echo URL ?>images/download_pdf.png" /></a></div>
</div>
Can anyone please help me in resolving this problem
As say #lasar missing $ in line 2 could be the problem.
I adapt (and test) your code to be more secure (see basename) and direct (see readfile):
<?php
$path = $_SERVER['DOCUMENT_ROOT']."/product_images/"; // change the path to fit your websites document structure
$fullPath = $path.basename($_REQUEST['download_file']);
if (is_readable ($fullPath)) {
$fsize = filesize($fullPath);
$path_parts = pathinfo($fullPath);
$ext = strtolower($path_parts["extension"]);
switch ($ext) {
case "pdf":
header("Content-type: application/pdf"); // add here more headers for diff. extensions
header("Content-Disposition: attachment; filename=\"".$path_parts["basename"]."\""); // use 'attachment' to force a download
break;
default;
header("Content-type: application/octet-stream");
header("Content-Disposition: filename=\"".$path_parts["basename"]."\"");
}
header("Content-length: $fsize");
header("Cache-control: private"); //use this to open files directly
readfile($fullPath);
exit;
} else {
die("Invalid request");
}
// example: place this kind of link into the document where the file download is offered:
// Download here
ADD
see readfile manual page for a good explanation of headers to
download files
REMEMBER due it's nature PHP is well know to damage binary file download, remeber to keep <?php always in 1st line and avoid close tag ?> in PHP-only files
I have created a file, using fopen('contacts','w').
now i want to prompt user to save this file where he want in his local machine(using php).
Any suggestion or sample code will be appreciated.
Thanks!!
Assuming your file - "contacts" is a physical file exists now in the server.
<?php
$file = 'contacts.csv';
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;
}
?>
Ref: http://php.net/manual/en/function.readfile.php
Download code
<?php
// place this code inside a php file and call it f.e. "download.php"
$path = $_SERVER['DOCUMENT_ROOT']."/path2file/"; // change the path to fit your websites document structure
$fullPath = $path.$_GET['download_file'];
if ($fd = fopen ($fullPath, "r")) {
$fsize = filesize($fullPath);
$path_parts = pathinfo($fullPath);
$ext = strtolower($path_parts["extension"]);
switch ($ext) {
case "pdf":
header("Content-type: application/pdf"); // add here more headers for diff. extensions
header("Content-Disposition: attachment; filename=\"".$path_parts["basename"]."\""); // use 'attachment' to force a download
break;
default;
header("Content-type: application/octet-stream");
header("Content-Disposition: filename=\"".$path_parts["basename"]."\"");
}
header("Content-length: $fsize");
header("Cache-control: private"); //use this to open files directly
while(!feof($fd)) {
$buffer = fread($fd, 2048);
echo $buffer;
}
}
fclose ($fd);
exit;
// example: place this kind of link into the document where the file download is offered:
// Download here
?>