See download progress with this php download script? - php

I'm using this script to download files and it works, but I don't get any download progress in % or time in my browser, it just says unknown. Is it possible to tweak the code to add that parameter? And apart from that, do you guys see any other weird things in the code or anything that can be improved? Thanks!
<?php
$filepath = 'x';
$title = 'y';
$download = true;
header("Cache-control: private");
header("Content-Type: application/octet-stream");
if ($download) {
header("Content-Disposition: attachment; filename=\"" . $title . "\"");
header('Content-Transfer-Encoding: binary');
} else {
header("Content-Disposition: inline; filename=\"" . $title . "\"");
}
// Disable caching
header('Cache-Control: no-cache, no-store, must-revalidate'); // HTTP 1.1.
header('Pragma: no-cache'); // HTTP 1.0.
header('Expires: 0'); // Proxies.
readfile($filepath);
exit;
?>

The server is not sending a Content-Length header, so the client cannot know how much more data to expect, and cannot display the progress. If the response consists of the contents of a file, you can obtain the file size by calling stat($filepath).

Related

php file_put_contents save in local client real path [duplicate]

I want the user to be able to download some files I have on my server, but when I try to use any of the many examples of this around the internet nothing seems to work for me. I've tried code like this:
<?php
$size = filesize("Image.png");
header('Content-Description: File Transfer');
header('Content-Type: image/png');
header('Content-Disposition: attachment; filename="Image.png"');
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: ' . $size);
readfile("Image.png");
I've even tried to use the most basic example I could find, like this:
<?php
header('Content-type: image/png');
header('Content-Disposition: attachment; filename="Image.png"');
readfile('Image.png');
When I've tested this I have removed all the other code I have and used an empty file with just this code to remove any faults created by external sources.
When I look in the console the file gets sent with the right headers i.e
'Content-Disposition: attachment; filename="Image.png"'
But the save dialog isn't displayed.
I've also tried with inline instead of attachment in the content disposition header but that didn't make a difference either, I've tested this in Firefox 8.0.1 Chrome 15.0.874.121 and Safari 5.1.1.
I’m pretty sure you don’t add the mime type as a JPEG on file downloads:
header('Content-Type: image/png');
These headers have never failed me:
$quoted = sprintf('"%s"', addcslashes(basename($file), '"\\'));
$size = filesize($file);
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename=' . $quoted);
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');
header('Content-Length: ' . $size);
This worked for me like a charm for downloading PNG and PDF.
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="'.$file_name.'"');
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_url)); //Absolute URL
ob_clean();
flush();
readfile($file_url); //Absolute URL
exit();
Based on Farhan Sahibole's answer:
header('Content-Disposition: attachment; filename=Image.png');
header('Content-Type: application/octet-stream'); // Downloading on Android might fail without this
ob_clean();
readfile($file);
This is all I needed for this to work. I stripped off anything that isn't required for this to work.
Key is to use ob_clean();
The problem was that I used ajax to post the message to the server, when I used a direct link to download the file everything worked fine.
I used this other Stackoverflow Q&A material instead, it worked great for me:
Ajax File Download using Jquery, PHP
its work for me
$attachment_location = "filePath";
if (file_exists($attachment_location)) {
header($_SERVER["SERVER_PROTOCOL"] . " 200 OK");
header("Cache-Control: public"); // needed for internet explorer
header("Content-Type: application/zip");
header("Content-Transfer-Encoding: Binary");
header("Content-Length:".filesize($attachment_location));
header("Content-Disposition: attachment; filename=filePath");
readfile($attachment_location);
die();
} else {
die("Error: File not found.");
}
the htaccess solution
<filesmatch "\.(?i:doc|odf|pdf|cer|txt)$">
Header set Content-Disposition attachment
</FilesMatch>
you can read this page:
https://www.techmesto.com/force-files-to-download-using-htaccess/
Here is a snippet from me in testing... obviously passing via get to the script may not be the best... should post or just send an id and grab guid from db... anyhow.. this worked. I take the URL and convert it to a path.
// Initialize a file URL to the variable
$file = $_GET['url'];
$file = str_replace(Polepluginforrvms_Plugin::$install_url, $DOC_ROOT.'/pole-permitter/', $file );
$quoted = sprintf('"%s"', addcslashes(basename($file), '"\\'));
$size = filesize($file);
header( "Content-type: application/octet-stream" );
header( "Content-Disposition: attachment; filename={$quoted}" );
header( "Content-length: " . $size );
header( "Pragma: no-cache" );
header( "Expires: 0" );
readfile( "{$file}" );

correct PHP headers for pdf file download

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);

Trying to generate a php download link. Name of file will not set

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

Force file download with php using header()

I want the user to be able to download some files I have on my server, but when I try to use any of the many examples of this around the internet nothing seems to work for me. I've tried code like this:
<?php
$size = filesize("Image.png");
header('Content-Description: File Transfer');
header('Content-Type: image/png');
header('Content-Disposition: attachment; filename="Image.png"');
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: ' . $size);
readfile("Image.png");
I've even tried to use the most basic example I could find, like this:
<?php
header('Content-type: image/png');
header('Content-Disposition: attachment; filename="Image.png"');
readfile('Image.png');
When I've tested this I have removed all the other code I have and used an empty file with just this code to remove any faults created by external sources.
When I look in the console the file gets sent with the right headers i.e
'Content-Disposition: attachment; filename="Image.png"'
But the save dialog isn't displayed.
I've also tried with inline instead of attachment in the content disposition header but that didn't make a difference either, I've tested this in Firefox 8.0.1 Chrome 15.0.874.121 and Safari 5.1.1.
I’m pretty sure you don’t add the mime type as a JPEG on file downloads:
header('Content-Type: image/png');
These headers have never failed me:
$quoted = sprintf('"%s"', addcslashes(basename($file), '"\\'));
$size = filesize($file);
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename=' . $quoted);
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');
header('Content-Length: ' . $size);
This worked for me like a charm for downloading PNG and PDF.
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="'.$file_name.'"');
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_url)); //Absolute URL
ob_clean();
flush();
readfile($file_url); //Absolute URL
exit();
Based on Farhan Sahibole's answer:
header('Content-Disposition: attachment; filename=Image.png');
header('Content-Type: application/octet-stream'); // Downloading on Android might fail without this
ob_clean();
readfile($file);
This is all I needed for this to work. I stripped off anything that isn't required for this to work.
Key is to use ob_clean();
The problem was that I used ajax to post the message to the server, when I used a direct link to download the file everything worked fine.
I used this other Stackoverflow Q&A material instead, it worked great for me:
Ajax File Download using Jquery, PHP
its work for me
$attachment_location = "filePath";
if (file_exists($attachment_location)) {
header($_SERVER["SERVER_PROTOCOL"] . " 200 OK");
header("Cache-Control: public"); // needed for internet explorer
header("Content-Type: application/zip");
header("Content-Transfer-Encoding: Binary");
header("Content-Length:".filesize($attachment_location));
header("Content-Disposition: attachment; filename=filePath");
readfile($attachment_location);
die();
} else {
die("Error: File not found.");
}
the htaccess solution
<filesmatch "\.(?i:doc|odf|pdf|cer|txt)$">
Header set Content-Disposition attachment
</FilesMatch>
you can read this page:
https://www.techmesto.com/force-files-to-download-using-htaccess/
Here is a snippet from me in testing... obviously passing via get to the script may not be the best... should post or just send an id and grab guid from db... anyhow.. this worked. I take the URL and convert it to a path.
// Initialize a file URL to the variable
$file = $_GET['url'];
$file = str_replace(Polepluginforrvms_Plugin::$install_url, $DOC_ROOT.'/pole-permitter/', $file );
$quoted = sprintf('"%s"', addcslashes(basename($file), '"\\'));
$size = filesize($file);
header( "Content-type: application/octet-stream" );
header( "Content-Disposition: attachment; filename={$quoted}" );
header( "Content-length: " . $size );
header( "Pragma: no-cache" );
header( "Expires: 0" );
readfile( "{$file}" );

Chrome has "Failed to load PDF document" error message on inline PDFs

I have a problem with reading pdf file in Chrome by using PHP.
The following code is how I do in PHP
$path = "actually file path";
header("Pragma: public");
header("Expires: 0");
header("Content-type: $content_type");
header('Cache-Control: private', FALSE);
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header("Content-Disposition: inline; filename=\"$filename\"");
header('Content-Transfer-Encoding: binary');
header('Content-Length' . filesize($path));
ob_clean();
flush();
readfile($path);
In here, I set the Content-Disposition to inline. Because I want to display the pdf file if user browser have build-in pdf viewer plugin. As you may know, Chrome has build-in pdf viewer.
The problem is I have bunch of pdf files on the server. Only some of them can be viewed by Chrome. I can't figure out why others can not work the same way. I have checked the permission of each files. It looks like not the permission problem.
Is there anyone know what the problem is? Thank you.
I've been wrestling with this same issue. This is as close as I got to consistent results across browsers. I think that the reason you could be having problems is if some PDF's are too large for readfile() to handle correctly. Try this:
$file = "path_to_file";
$fp = fopen($file, "r") ;
header("Cache-Control: maxage=1");
header("Pragma: public");
header("Content-type: application/pdf");
header("Content-Disposition: inline; filename=".$myFileName."");
header("Content-Description: PHP Generated Data");
header("Content-Transfer-Encoding: binary");
header('Content-Length:' . filesize($file));
ob_clean();
flush();
while (!feof($fp)) {
$buff = fread($fp, 1024);
print $buff;
}
exit;
I had similar issue but I noticed the order matters. Seems that ; filename= must have quotes around it, Content-Disposition: attachment Try this:
$file = "/files/test.pdf";
$finfo = finfo_open(FILEINFO_MIME_TYPE); // return mime type ala mimetype extension
$mime = finfo_file($finfo, $file);
header('Pragma: public');
header('Expires: 0');
header('Content-Type: $mime');
header('Content-Description: File Transfer');
header('Content-Disposition: attachment; filename="'.basename($file).'"'));
header('Content-Transfer-Encoding: binary');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Content-Length' . filesize($file));
ob_clean();
flush();
readfile($file);
i've fixed this way
$path = 'path to PDF file';
header("Content-Length: " . filesize ( $path ) );
header("Content-type: application/pdf");
header("Content-disposition: inline; filename=".basename($path));
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
ob_clean();
flush();
readfile($path);
Had the same problem, chrome didn't display the inline PDF, stuck at loading. The solution was to add header('Accept-Ranges: bytes').
My complete code:
header('Content-Type: application/pdf');
header('Content-Disposition: inline; filename="'.$title.'"');
header('Content-Transfer-Encoding: binary');
header('Content-Length: '.filesize($file));
header('Accept-Ranges: bytes');
header('Expires: 0');
header('Cache-Control: public, must-revalidate, max-age=0');
For me adding the following header fixed this annoying Chrome bug (?):
header('HTTP/1.1 200 OK');
After hours wasted this...i added comments to point out that #Kal has the only solution that worked. But somehow that's not enough...this is such an impossible and frustrating problem when Chrome does this:
Error Failed to load PDF document. Reload
Here is the diff that ended the torture.
- // Waste time with chrome:
- header("Content-type:application/pdf");
- header("Content-Disposition:attachment;filename=$file_basename");
- readfile($file);
exit();
---------------------------
+ // Deliver the file:
+ header('Pragma: public');
+ header('Expires: 0');
+ header('Content-Type: $mime');
+ header('Content-Description: File Transfer');
+ header('Content-Disposition: attachment; filename="'.basename($file).'"');
+ header('Content-Transfer-Encoding: binary');
+ header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
+ header('Content-Length'.filesize($file));
+ ob_clean();
+ flush();
+ readfile($file);
exit();
For about thirty minutes i fooled with various variations of this...but i could not pin it down to "Add HTTP 200", not to "add bytes", not to "quote your filename", not to "separate the file ending". None of those worked.
(Thank you again #Kal).
I was having this issue, struggled for almost 6 hours and finally got it working. My solution is similar to the above answers but the above answers are not completed. There are three steps to solve this issue.
Step 1.
Go to php.ini file and add this line.
output_buffering = False
Step 2.
This error comes if you are opening a large PDF file. So, to solve this, just before adding headers, make sure you put these two lines.
set_time_limit(0);
ini_set('memory_limit', '100M'); //the memory limit can be more or less depending on your file
Step 3.
Add below headers and the code to read the file, so the final code would like this.
set_time_limit(0);
ini_set('memory_limit', '100M');
$file = "path/to/file.pdf";
header('Content-Type: application/pdf');
header('Content-Disposition: inline;
filename="yourfilename.pdf"'); //not the path but just the name
header('Content-Transfer-Encoding: binary');
header('Content-Length: '.filesize($file));
header('Accept-Ranges: bytes');
header('Expires: 0');
header('Cache-Control: public, must-revalidate, max-age=0');
ob_clean();
flush();
readfile($file);
exit();
100% working solution. If you have any issues, let me know :)

Categories