Windows compatibility error downloading exe files in PHP - php

I have set up a page using php and mysql that requires user to log in to download various paid for programs. They can click on a link as here and the program downloads and runs correctly.
$c3 = mysql_result($result,$i,"exe");
echo "<a href='$c3'>... etc
However, RT-click properties lets them see the path to that file, so I changed the above to:
$c3="downloads3.php?link=".mysql_result($result,$i,"exe");
Where downloads3.php is as follows:
<?php
$file = $_GET['link'];
$size = filesize($file);
$type = filetype($file);
$path = "../downloads/";
header('Content-Type: $type');
header("Content-Transfer-Encoding: Binary");
header("Content-Disposition: attachment; filename=$path.$file");
header("Content-Length: ".filesize($file));
readfile($file_url);?>
?>
It finds the correct file and I get a security warning but on clicking run anyway it immediately gives a windows error message that the file is not compatible with this version of windows. Must be something in the above header but can't figure out what. Tried various permutations.
Any brill ideas, either of getting the above to work or other ways of hiding the source path? Thanks.

It's far more likely that the EXE is getting corrupted due to unexpected output. Your downloads3.php file has some extra output that will appear in the download:
readfile($file_url);?> //PHP stops parsing here
?> //output "\n?>"
The PE header itself tells Windows what versions it can run on, so if any errors get generated before the file gets sent, they'll appear in the place Windows is expecting the header.
To mitigate this you can remove the extra newline and ?> at the end of the file and turn error reporting off with error_reporting(0) at the top of the file.

The Best solution for here to get download file with any name what do you have want
function force_download($filename = '', $data = '')
{
if ($filename == '' OR $data == '')
{
return FALSE;
}
// Try to determine if the filename includes a file extension.
// We need it in order to set the MIME type
if (FALSE === strpos($filename, '.'))
{
return FALSE;
}
// Grab the file extension
$x = explode('.', $filename);
$extension = end($x);
// Load the mime types
if (defined('ENVIRONMENT') AND is_file(APPPATH.'config/'.ENVIRONMENT.'/mimes'.EXT))
{
include(APPPATH.'config/'.ENVIRONMENT.'/mimes'.EXT);
}
elseif (is_file(APPPATH.'config/mimes'.EXT))
{
include(APPPATH.'config/mimes'.EXT);
}
// Set a default mime if we can't find it
if ( ! isset($mimes[$extension]))
{
$mime = 'application/octet-stream';
}
else
{
$mime = (is_array($mimes[$extension])) ? $mimes[$extension][0] : $mimes[$extension];
}
// Generate the server headers
if (strpos($_SERVER['HTTP_USER_AGENT'], "MSIE") !== FALSE)
{
header('Content-Type: "'.$mime.'"');
header('Content-Disposition: attachment; filename="'.$filename.'"');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header("Content-Transfer-Encoding: binary");
header('Pragma: public');
header("Content-Length: ".strlen($data));
}
else
{
header('Content-Type: "'.$mime.'"');
header('Content-Disposition: attachment; filename="'.$filename.'"');
header("Content-Transfer-Encoding: binary");
header('Expires: 0');
header('Pragma: no-cache');
header("Content-Length: ".strlen($data));
}
exit($data);
}
$data = 'Here is some text!';
$name = 'mytext.txt';
force_download($name, $data);

DOH!!!!!!!!!!!!!!!! Too much cutting and pasting, that code has a really stupid error readfile($file_url) should be readfile($file), no wonder my 36Mb file was only 1KB after download, it was empty!
Thanks for all the comments, apologies for wasting your time.

Related

PHP - Error with serve files

Here is my code. I wrote this to serve mp3, images and videos. Mp3 files are received and working well. Images and videos are received but corrupted. I'm new to php.
<?php
if( !empty( $_GET['type']|| $_GET['name']|| $_GET['ext'] ) ) {
// check if user is logged
if(true) {
$type = preg_replace( '#[^-\w]#', '', $_GET['type'] );
$name = $_GET['name'] ;
$file = "{$_SERVER['DOCUMENT_ROOT']}/cont/{$type}/{$name}";
echo $file;
if (file_exists($file)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="'.basename($file).'"');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
readfile($file);
exit;
}
}
}
die( "ERROR: invalid file or you don't have permissions to download it." );
Can you help me?
There is an echo $file; before the actual response that doesn't belong there.
Besides the text itself, PHP also produces a Warning on the first call to header(). Both these arrive in the final content before the file header and makes the data received by the browser unrecognizable by most file readers.

Php- I have not got my output for download corrupted files

I am not able to open the file after the download.
It says the the file has been corrupted.
I guess i have used all the required headers fine.
In chrome it shows error like:
chrome resource interpreted as document but transferred with mime type application/octet-stream
In Firefox no error msg.
if (isset($_GET['file']) && basename($_GET['file']) == $_GET['file']) {
$filename = $_GET['file'];
} else {
$filename = NULL;
}
$err = 'Sorry, the file you are requesting is unavailable.';
if ($filename) {
// define the path to your download folder plus assign the file name
$path = '/wp-content/uploads/'. $filename;
// check that file exists and is readable
if (file_exists($path)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="'. basename($path) . '"');
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));
ob_end_clean();
flush();
readfile($path);
exit;
}
}
download: getting downloaded from ftp folder.
None of the formats are opening.
.txt is getting opened.
Let me know if i am in wrong direction.
Inserting into table:
echo "<tr><a href='?file=". $row["FileupName"]."'>".$row["FileupName"]."</td></tr>";
readfile('$path') is your issue, it should be readfile($path) (with no quotes)
In PHP, variables are only evaluated in strings if the string is defined in double quotes ". Effectively you're downloading a file where the contents is the literal string '$path', with an incorrect filesize.

PHP readfile() echoes file content to the screen, but doesn't download

the code I am using:
function DownLoading($Peter)
{
// if(ini_get('zlib.output_compression'))
// ini_set('zlib.output_compression', 'Off')
$File = "";
$Filename = "";
If ($Peter == "Farm") {
$File = "TestFile.txt";
$FileName = $File; //"TestFile.txt";
$len = filesize($File); // Calculate File Size
if (file_exists("TestFile.txt")) {
header('Content-Description: File Transfer');
header('Content-Type: text/plain');
header('Content-Disposition: attachment; filename="TestFile.txt"');
header('Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . $len);
ob_clean();
$wasdownloaded = readfile("TestFile.txt");
if ($wasdownloaded === false)
echo "error";
else {
echo "no error";
Flush();
exit;
}
}
}
}
The strange thing is that if I run this code on wamp server then it works fine (no echoeing, but downloading)
The following is echoed to the sdcreen: This is a test file!!! Nowno error
whereby "This is a test file!!! NOW" is the files's content
Can somebody help me?
I did something very stupid that was causing the same thing. Basically, as already said, you must ensure nothing has been sent already.
I had put a space before the <?php opening declaration - and that was the problem!

headers sent but download doesn't start (force download)

I have a lightbox with a form, when the user sends the form a download should start, this is the code I use:
function start_download( $path, $item ) {
$file = $path.$item;
header("Content-type:application/pdf");
header('"Content-Disposition:attachment;filename="'.$file.'"');
}
Unless the fact that is a function is a problem, I think it should work right? well it doesn't. No error whatsoever.
Looking at Chrome's developer tools I can see that the headers are actually set application/pdf.
Oh, also, when I add readfile($file) it seems to read the file but it returns a strange string (numbers and weird symbols).
I searched over this site but nothing seems to work. I really don't know what else can I do. Ideas?
BTW if I "echo" the $file it shows the url correctly, I don't think that is the problem.
You've got wonky quotes, for one
header('"Content-Disposition:attachment;filename="'.$file.'"');
^^--- why double quoting?
They're breaking the header call.
Try:
header("Content-Disposition: attachment; filename=$file");
Note that I've put some spaces in there. They're strictly speaking not necessary, but they do help with legibility.
Try the following:
function start_download( $path, $item ) {
$file = $path.$item;
if (file_exists($file)) {
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename=' . $item);
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();
if (readfile($file) !== FALSE) return TRUE;
} else {
die('File does not exist');
}
}
function start_download( $path, $item ) {
$file = $path.$item;
header("Content-Type: application/pdf");
header('Content-Disposition: attachment;filename="'.basename($file) . '"');
readfile($file);
}
As far as I can see this may work, as long as $file is a valid local path name to a pdf file. Make sure, there is absolutely no other output!

Serve file to user over http via php

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.

Categories