below is some part of code in my download gateway
if (!isset($_GET['f']) || empty($_GET['f'])) {die("<h1>URL Malfunction</h1><br/><p><i>Please Try Later</i>");}
if (strpos($_GET['f'], "\0") !== FALSE){ die("<h1>URL Malfunction</h1><br/><p><i>Please Try Later</i>");}
#Check URL, find resource Path
$fileName = basename($_GET['f']);
$file_path=(string)makeDownloadFilePath($fileName,"dir");
if(!is_file($file_path)){die("<h1>404 Not found</h1><br/><p><i>The resource you requested is not available</i>");}
$fileSize = filesize($file_path);
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: public"); #Build Response#
header("Content-Description: File Transfer");
header("Content-Type: application/force-download");
header("Content-Disposition: attachment; filename=\"$fileName\"");
header("Content-Transfer-Encoding: binary");
header("Content-Length: " . $fileSize);
$file = #fopen($file_path,"rb");
if ($file) {
while(!feof($file)) { #File Transfer#
print(fread($file, 1024*8));
flush();
if (connection_status()!=0) {
#fclose($file);
die();
}
}
#fclose($file);
//The File is Downloaded . Closing Connections
I am using GET method to receive the filename. The filename and its path will e genrated from gateway. Now the problem is When i click on download in a page, instead of showing a Download dialog, the browser just renders the file content as text on screen. For eg, i am downloading foo.mp3. the binary contents are displayed as weird text on screen.
Its echoing a warning like: We cannot change the Headers. headers already sent to ...
Can any one tell , where i had made the mistake?
Thanks
We cannot change the Headers. headers already sent to..
This error comes when you print any thing before php your header command.
The most common cause of this error by a long, long way is that you have some leading white-space before the opening <?php tag in your file (or one of it's includes).
The < should be the first character in the file, anything before it is written to the output buffer directly and will probably result in the headers being sent. When forcing file download in this manner, it will also result in corrupted files.
Use readfile instead of fopen as follow and use ob_clean() , ob_flush() :
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="'.$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($musicPath));
ob_clean();
flush();
readfile($musicPath);
ob_flush();
Are you using the output buffer?
try adding ob_start(); before you send out the header information, this may solve your issue.
You can find out more information about it here
Thanks all for the help. The problem was i was using a
error_reporting(E_ALL);
ini_set('display_errors', true);
flush();
for debugging in one of my includes.
I just removed it.Now it works.
Related
I am facing some problems while generating PDF reports from my application in firefox(ubuntu machine).
my code is:
<?php
$path = "path_to_file" ;
$file = "test.pdf";
header('Content-type: application/pdf');
header("Content-disposition: attachment; filename=$file");
readfile($path);
return new Response("Success");
code is working:
when the PDF-report contains data
when size is more than 1 kb
In windows machine
not working:
when report contains no data or size is in bytes.
It is Generating a binary sting in a new tab in browser instead of generating blank-PDF.
Please help me fixing this issue.Thanks in advance.
Got my answer.This may help others.
<?php
$path = "path_to_file" ;
$file = "test.pdf";
header("Content-disposition: attachment; filename= $file"); //Tell the filename to the browser
header("Content-type: application/pdf");//Get and show report format
header("Content-Transfer-Encoding: binary");
header("Accept-Ranges: bytes");
readfile($path); //Read and stream the file
get_curret_user();
I would do it in this way to avoid some problems with browser applications and caching. Give it a try:
<?php
$path = "path_to_file" ;
$file = "test.pdf";
$content = file_get_contents($path);
header("Content-disposition: attachment; filename=\"".$file."\"");
header("Content-type: application/force-download");
header("Content-Transfer-Encoding: binary");
header("Content-Length: ".strlen($content));
header("Pragma: no-cache");
header("Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0");
header("Expires: 0");
echo $content;
die();
EDIT:
If it's really necessary to use the pdf plugin of the browser instead of downloading and opening it immediately with the associated default pdf reader, please replace
header("Content-type: application/force-download");
with
header("Content-type: application/pdf");
I'm trying to download a CSV file through the browser. The script is partially working, because so far I managed to display the CSV on screen, but the download is not starting.
Here is what i tried so far:
if(isset($currency)) {
header("Content-Type: application/csv");
header("Content-Disposition: attachment;Filename=Pricelogs.csv");
ob_clean();
$filename = "/tmp/".uniqid().".csv";
exportCSVFile($filename, $currency, $country, $provider);
readfile($filename);
//unlink("'".$filename."'");
} else {
echo "ERR_USERNAME_PASSWORD";
exit();
}
I had already read all questions of this type from FAQ & also tried but it gets open on browser only,instead of downloading.
I had also used header with single quotes.
I also tried header("Content-Type: text/csv");
Also:
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/force-download");
header("Content-Disposition: attachment; filename=\"".$filename."\";" );
header("Content-Transfer-Encoding: binary");
PUT your CSV file URL, it will display in browser in place of force browser to download. You can open it in iframe in your site.
http://docs.google.com/viewer?embedded=true&url=www.yoursite.com/filename.csv
I usually just do:
header('Content-type: text/csv');
header("Content-Disposition: attachment; filename=my_csv_filename.csv");
// print CSV lines here
exit();
I can tell you this combination is working for me:
$bom = chr(0xEF) . chr(0xBB) . chr(0xBF);
header("Content-type: application/csv; charset=UTF-8");
header("Content-Disposition: attachment; filename=$filename.csv");
header("Pragma: no-cache");
header("Expires: 0");
print $bom . $data;
exit;
If I were you, I would first test this plainly (outside of all your buffering), first see that you manage to make this work, and only then test it in your specific set up.
You might try this.
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: private",false);
header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename=\"$filename.csv\";" );
print $content;
For large files you need to get your output buffer started
add : ob_start(); at the start
ob_clean(); at the end of you file
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
try to download file and getting invalid file in response in core php
$filename=gallery/downloads/poster/large/h.jpg
path to download file is correct but don't know why it give invalid file in return ...
$filename = $_GET["filename"];
$buffer = file_get_contents($filename);
/* Force download dialog... */
header("Content-Type: application/force-download");
header("Content-Type: application/octet-stream");
header("Content-Type: application/download");
header('Content-Type: image/jpeg');
/* Don't allow caching... */
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
/* Set data type, size and filename */
header("Content-Type: application/octet-stream");
header("Content-Transfer-Encoding: binary");
header("Content-Length: " . strlen($buffer));
header("Content-Disposition: attachment; filename=$filename");
/* Send our file... */
echo $buffer;
if u have a better way then please share .... thanks in advance .
A better solution would be:
$filename = $_GET["filename"];
// Validate the filename (You so don't want people to be able to download
// EVERYTHING from your site...)
if (!file_exists($filename))
{
header('HTTP/1.0 404 Not Found');
die();
}
// A check of filemtime and IMS/304 management would be good here
// Be sure to disable buffer management if needed
while(ob_get_level()) {
ob_end_clean();
}
// Do not send out full path.
$basename = basename($filename);
Header('Content-Type: application/download');
Header("Content-Disposition: attachment; filename=\"$basename\"");
header('Content-Transfer-Encoding: binary'); // Not really needed
Header('Content-Length: ' . filesize($filename));
Header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
readfile($filename);
That said, what does "invalid file" mean? Bad length? Zero length? Bad file name? Wrong MIME type? Wrong file contents? The meaning may be clear to you with everything under your eyes, but from our end it's far from obvious.
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 :)
If I goto http://site.com/uploads/file.pdf I can retrieve a file.
However, if I have a script such as:
<?php
ini_set('display_errors',1);
error_reporting(E_ALL|E_STRICT);
//require global definitions
require_once("includes/globals.php");
//validate the user before continuing
isValidUser();
$subTitle = "Attachment";
$attachmentPath = "/var/www/html/DEVELOPMENT/serviceNow/selfService/uploads/";
if(isset($_GET['id']) and !empty($_GET['id'])){
//first lookup attachment meta information
$a = new Attachment();
$attachment = $a->get($_GET['id']);
//filename will be original file name with user name.n prepended
$fileName = $attachmentPath.$_SESSION['nameN'].'-'.$attachment->file_name;
//instantiate new attachmentDownload and query for attachment chunks
$a = new AttachmentDownload();
$chunks= $a->getRecords(array('sys_attachment'=>$_GET['id'], '__order_by'=>'position'));
$fh = fopen($fileName.'.gz','w');
// read and base64 encode file contents
foreach($chunks as $chunk){
fwrite($fh, base64_decode($chunk->data));
}
fclose($fh);
//open up filename for writing
$fh = fopen($fileName,'w');
//open up filename.gz for extraction
$zd = gzopen($fileName.'.gz', "r");
//iterate over file and write contents
while (!feof($zd)) {
fwrite($fh, gzread($zd, 60*57));
}
fclose($fh);
gzclose($zd);
unlink($fileName.'.gz');
$info = pathinfo($fileName);
header('Content-Description: File Transfer');
header('Content-Type: '.Mimetypes::get($info['extension']));
header('Content-Disposition: attachment; filename=' . basename($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($fileName));
ob_clean();
flush();
readfile($fileName);
exit();
}else{
header("location: ".$links['status']."?".urlencode("item=incident&action=view&status=-1&place=".$links['home']));
}
?>
This results in sending me the file, but when I open it I receive an error saying:
"File type plain text document (text/plain) is not supported"
First off, I'd start by checking the HTTP headers. You can do this in Firefox easily using the "Live HTTP headers" extension; not sure about equivalents in other browsers offhand. This will let you verify if the header is actually getting set to "application/pdf" and whether your other headers are getting set as well.
If none of the headers are getting set, you might be inadvertently sending output before the calls to header(). Is there any whitespace before the <?php tag?
Are you sure application/pdf is the header your browser is actually seeing?
You can check that out with various HTTP dev tools, for instance HTTP Client for the Mac or Firebug for Firefox.
I use this one and it works.
if(file_exists($file_serverfullpath))
{
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: private", false);
//sending download file
header("Content-Type: application/octet-stream"); //application/octet-stream is more generic it works because in now days browsers are able to detect file anyway
header("Content-Disposition: attachment; filename=\"" . basename($file_serverfullpath) . "\""); //ok
header("Content-Transfer-Encoding: binary");
header("Content-Length: " . filesize($file_serverfullpath)); //ok
readfile($file_serverfullpath);
}
Try prepending "error_reporting(0);". I found this in the comments at http://php.net/readfile (where you took this example from).
Another thing that could be a problem is your file size. There have been issues reported in the past about PHP5 (we're talking 2005 here, so i hope this is fixed by now) having trouble reading files >2MB. If your file size exceeds this you may want to verify that it reads the whole file.