Unable to download file using readfile - php

I try to offer a pdf-file-download, handeled in dwhandler.php.
All this is supposed to do is open the pdf-file or start a download of it.
I tried:
<?php
header("Content-Description: File Transfer");
header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename='Paper.pdf'");
header("Cache-Control: must-revalidate");
readfile("Paper.pdf");
exit;
?>
I also tried some other headers, but none worked.
The browser keeps opening the file directly in some weird coding. Here is a pic of the first few lines:
http://www.directupload.net/file/d/3865/h8waniq9_jpg.htm
Has anybody an idea why this is happening? I have no idea what is left to try...
Thank you very much!

is html not a option? I know you can offer files to download with simply using html 5 by doing
<a href="example.pdf" download>download not open it</a>
Take a look into: Forcing to download a file using PHP

<?php
// Do your Sql query
header('Location: http://host/files/pdf/file.pdf'); // redirect user to actualy location
?>

Related

Why is my PDF download corrupted?

I have a script that generates a pdf using fpdf, this file is saved correctly on the server on my computer. In that same php file I run the following code to download the file. When i download the pdf and I check it in notepad, everything in the pdf is the same, except for the fact that it contains a lot of my previous files html at the beginning of it. The file saved to my server doesn't have any of that.
What could cause something like this to happen? I have no idea where to look for the source of this error, can anyone point me in the direction to finding the problem?
<?php
$filename=($name.$ran.'.pdf');
$pdf->Output($name.$ran.'.pdf');
header ("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header('Content-Type: application/octetstream');
header("Content-Transfer-Encoding: Binary");
header("Content-length: ".filesize($filename));
header("Content-disposition: attachment; filename=\"".basename($filename)."\"");
readfile($name.$ran.'.pdf');
?>
I managed to figure things out, thanks to hakre! Essentially I just needed to clear out the output buffer using ob_clean () before using readfile() and the code worked!

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.

Hide download file location. - Redirect download

I am selling a digital product and want to hide the true location of the download.
So I'm using a redirect script like this:
protected function redirectDownload ($realfilename) {
ob_start();
$mm_type="application/octet-stream";
header("Cache-Control: public, must-revalidate");
header("Pragma: no-cache");
header("Content-Type: " . $mm_type);
header("Content-Length: " .(string)(filesize($realfilename)) );
header('Content-Disposition: attachment; filename="'.$this->fakefilename.'"');
header("Content-Transfer-Encoding: binary\n");
ob_end_clean();
readfile($realfilename);
}
The zip file is always corrupted when I download it, but when I download it directly it is fine.
Does anyone know why this might be?
I think this was working fine on another server, but would need to confirm that.
If I can't solve this, is there any other techniques or services I can use to do this?
Open the downloaded(corrupted) file in an text-editor, i guess there has already been some output before you call the function.
You should better use ob_start() at the begin of your script instead of the begin of the function.

PHP generated Excel file is different when downloaded

I have a PHP file that generates xls files using the module found at http://pear.php.net/package/Spreadsheet_Excel_Writer/
I can create the sample document just fine and when I open it, it looks fine.
My next step it to turn it into a downloadable link. To do that, I did this:
$mimeType = "application/vnd.ms-excel";
$file_name = "test.xls";
$file_path = "/tmp/".$file_name;
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Content-Type: application/force-download");
header("Content-Type: application/octet-stream");
header("Content-Type: application/download");
header('Content-Type: application/' . $mimeType);
header('Content-Length: '.$size);
header("Content-Disposition: attachment;filename=$file_name ");
header("Content-Transfer-Encoding: binary ");
// open the file in binary read-only mode
// display the error messages if the file canĀ“t be opened
$file = & fopen($file_path, 'rb');
if ($file) {
// stream the file and exit the script when complete
fpassthru($file);
exit;
} else {
echo $err;
}
When I download the file however, it contains a lot of garbage data both in Excel and OpenOffice. The diff says that then binary file in the /tmp folder and the downloaded file are different from each other. I'm guessing that it has something to do with the headers or with fpassthru but I haven't had much luck with debugging the issue.
Any ideas on what the problem is?
The multiple Content-Type headers are uncessary. You're essentially saying that the file is a muffin and a pizza and a ford taurus all at the same time. All you need is the application/octet-stream version, unless you want to serve up the exact mime type.
As well, is there any reason you're trying to turn the file handle returned by fopen() into a reference?
Try something simpler:
<?php
header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment;filename=$file_name");
readfile("/tmp/test.xls");
exit();
?>
and see if that does any better.
Just make sure that you don't send ANYTHING out to the browser BEFORE the actual file content gets send.
It might just be some php 'error' or even 'notice' that Spreadsheet_Excel_Writer is producing and you don't even see. Or it might be a closing '?>' tag thats followed by s simple space or newline.
I had a similar error where the file that was generated inside the web folders were working. However the delivery using header('...') gave me corrupt files. This was due to a single space at the end of one php file after the closing '?>' tag.
I am using the same library and I just discovered that the files in the library itself are creating the whitespace.
Solution: In the following files remove the whitespace at the end of the file, or remove the ?> closing tag at the end.
Files to edit (all files in the Spreadsheet_Excel_Writer package):
Writer.php
Workbook.php
Worksheet.php
PPS.php
Parser.php
OLE.php
Parser.php
File.php
BIFFWriter.php
Validator.php
Root.php
Add the following code at the top of the page where the excel file is generated
ob_clean();
This would clear all the gibberish data.Also check for any echo statements.If echo statements are present, remove them. The data should always present in format specified by excel package.

php force download xml

I am creating an xml file on the fly. When a user generates this file I want it to open up a download file dialog with the content that was generated. There is no actual file because it is just generated through php. Any ideas on how to do this?
This is what worked for me. In readfile('newfile.xml'); make sure to give the path of the file correctly. This php page is called from an html page with anchor tag which says - download:
<?php
header('Content-disposition: attachment; filename="newfile.xml"');
header('Content-type: "text/xml"; charset="utf8"');
readfile('newfile.xml');
?>
source: How do I force the browser to download a file to disk instead of playing or displaying it?
Send a content-disposition attachment header.
header('Content-disposition: attachment; filename=advertise.xml');
header ("Content-Type:text/xml");
//output the XML data
echo $xml;
// if you want to directly download then set expires time
header("Expires: 0");

Categories