PHP downloads at 0 bytes - php

I have ZIP files in a directory that is one step up from the root directory (to prevent hotlinking etc...). Here is the code:
<?php
$filename = $_GET['id'];
if(!$filename){
header("Location: index.html");
} else {
function send_download($filename){
$file_path = '../../../../downloads/' . $filename . '.zip';
$file_size=#filesize($file_path);
header("Content-Type: application/x-zip-compressed");
header("Content-disposition: attachment; filename=$filename");
header("Content-Length: $file_size");
readfile($file_path);
exit;
}
send_download($filename);
}
?>
All the ZIP files are fine but using this method on an 'a' tag causes the downloads to be 0 bytes in file size! :(
Any ideas as to why?
Many thanks!

Can you try changing the Content-type to the following:
Content-type: application/x-zip;
And before you do, check if the file exists.
<?php
$filename = $_GET['id'];
if(!$filename){
header("Location: index.html");
} else{
function send_download($filename){
$file_path = '../../../../downloads/' . $filename . '.zip';
if (file_exists($file_path))
{
$file_size=#filesize($file_path);
header("Content-Type: application/x-zip-compressed");
header("Content-disposition: attachment; filename=$filename");
header("Content-Length: $file_size");
readfile($file_path);
exit;
}
send_download($filename);
}
else
die("Error 404!");
}
?>

header("Location: http://www.fqdn.tld/file.ext");
Based on _GET["id"] being > 0 and not null, you've created a function which has been used directly after, so you've just added more lines of code for no required purpose.
I see you have added an "#" sign as people have previously commented, however, the only way for you to begin fixing this is by:
Removing the # sign as you should never use it, very bad practice, you should cater for all exceptions in your code, it makes for a really good programmer. (Scripting in PHP)
error_reporting(E_ALL);
Place point b) on it's own line but after the <?php - so we can see a full list of errors.
Your code is fine, the problem you have is permissions, ensure that apache has access to your "files" repository, the fact you are able to check that the file is there suggest slight permissions and the files exists, the point that 0 bytes are being returned suggest reading privileges are denied at Apache level.

Right, after a bit of Googling and some blood, sweat and tears I have finally found a solution!
<?php
$filename = $_GET['id'];
header('Content-type: application/zip');
header("Content-Disposition: attachment; filename=" . $filename);
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
readfile('../../downloads/' . $filename . ".zip");
exit;
?>
Many thanks to all of whom shed some light on this!

And here is the code with the filesize:
<?php
$filename = $_GET['id'];
$file = "../../downloads/" . $filename . ".zip";
header('Content-type: application/zip');
header("Content-Disposition: attachment; filename=" . $file);
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Content-length: " . filesize($file));
readfile($file);
//echo filesize($file);
exit;
?>

Only one mistake we all are doing check below.
readfile($file); //$file should be relative not absolute. That's it.
Thanks,
Anirudh Sood.

Related

in PHP How to download the file from its file path?

I am new to PHP and trying my hands into it. I am creating a file and writing back to it. Creating a file in some path and writing to it, works fine for me. But when i try to download the same file from the same path, its not getting downloaded instead I'm getting empty file.
header('Content-type: text/xml');
header("Content-Disposition: attachment; filename=".'check.xml');
header("Content-Length: " . filesize('./download/'.$_SESSION['user_name'].'/check.xml'));
readfile('download/'.$_SESSION['user_name'].'/check.xml');
exit;
Hi, Thanks for everyone. But I saw very unusual thing. When i downloaded the file, I didn't got the full file.
Why this case
Try removing ./ from the start of the filepath, like follows:
header('Content-type: text/xml');
header("Content-Disposition: attachment; filename=".'check.xml');
header("Content-Length: " . filesize('download/'.$_SESSION['user_name'].'/check.xml'));
readfile('download/'.$_SESSION['user_name'].'/check.xml');
exit;
With Linux file systems, ./ means the root, so that's the equivalent of / and ../ means the directory above the current directory. It's best to use absolute file paths, but simply removing the ./ should suffice.
You will also need to flush the write buffers of PHP using flush()
Here is a good working function to download a file
Here is a version adapted from that page:
public static function downloadFile($fileName) {
$filePath = $fileName;
$size = filesize($filePath);
// Taken from http://w-shadow.com/blog/2007/08/12/how-to-force-file-download-with-php/
header("Content-type: text/plain");
header("Content-Disposition: attachment; filename=\"$fileName\"");
header("Content-Transfer-Encoding: binary");
header("Accept-Ranges: bytes");
// The three lines below basically make the download non-cacheable
header("Cache-control: private");
header("Pragma: private");
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header("Content-Length: " . $size);
if ($file = fopen($filePath, "r")) {
$buffer = fread($file, $size); // this only works for small files!
print $buffer;
flush();
fclose($file);
}
}

how to access file from outside root directory in php

I have a code to download zip files:
$dl_path = './';
$filename = 'favi.zip';
$file = $dl_path.$filename;
if (file_exists($file)) {
header('Content-Description: File Transfer');
header('Content-Type: application/zips');
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/download");
header("Content-Disposition:attachment;filename=$filename ");
header("Content-Transfer-Encoding:binary ");
header('Content-Length: ' . filesize($file));
ob_clean();
flush();
readfile($file);
exit;
}
there is root directory /public_html, the script is executing in root directory.
there is zip file in / directory.
i am trying to use the $dl_path as / but it is not working.
Please help.
$dl_path = __DIR__.'/..'; // parent folder of this script
$filename = 'favi.zip';
$file = $dl_path . DIRECTORY_SEPARATOR . $filename;
// Does the file exist?
if(!is_file($file)){
header("{$_SERVER['SERVER_PROTOCOL']} 404 Not Found");
header("Status: 404 Not Found");
echo 'File not found!';
die;
}
// Is it readable?
if(!is_readable($file)){
header("{$_SERVER['SERVER_PROTOCOL']} 403 Forbidden");
header("Status: 403 Forbidden");
echo 'File not accessible!';
die;
}
// We are good to go!
header('Content-Description: File Transfer');
header('Content-Type: application/zip');
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/download");
header("Content-Disposition: attachment;filename={$filename}");
header("Content-Transfer-Encoding: binary ");
header('Content-Length: ' . filesize($file));
while(ob_get_level()) ob_end_clean();
flush();
readfile($file);
die;
^ try this code. See if it works. If it doesn't:
If it 404's means the file is not found.
If it 403's it means you can't access it (permissions issue).
First of all check if your script is running under the correct directory by echoing dirname(__FILE__).
If it is running under public_html then you can change the code like this:
$dl = dirname(__FILE__). '/../';
But beware of security issue!
Check if you have read/write permission on the file and directory
Check the open_basedir restriction in php.ini (see How can I relax PHP's open_basedir restriction?)
Hope this helps

Downloading code is not working in wordpress [duplicate]

This question already has answers here:
Forcing to download a file using PHP
(10 answers)
Closed 9 years ago.
When I am downloading an image it's displaying these characters on screen.
�M\cIDATx��\i��v�U�ݳ��x���6`8�Y�&#��#D �����HDʟ'�~�z;a���D,�c������ƌ���ٺ�*�w�=շjz^z�ـ���UwWWݺ�;�|g��&H���o�Gy�𼖖��~s��K۲e�y�7�ѣG�̙3ͤI������3�O=�T���n�z�)�k�.�p�B��NJ��6m���؄a(�ٳgOt��i���|����hhh((�˦����{����3��sO�C�:�_�k�������s�)�|X�V��_C�6���2o~G���3����y۶m��o4�\s�) r�ܹse.|-[�,�`~/N� GQdU(h!Z� |E���J��h�&�u�sާ�ES�T���æ��ׯh�o�>���ˡ�ˠ�-��-m�{ �\p�#Mo؅u�֙���{�qN;,�ŋ�cߏ䦦&3u�T���)��MS�yrP���B|o���Ԏ�l1�C&L8�����j�j/_4ϯ���4��o�o��w�>|8�5���M�P�;f���͆ Ҿ&N�hJM%C�,Z�� Z=�9螞�=~��4�7H�������#���-"0�jWW�1���{[[[�:;'�Θ1�0�+�^h�h�>��#�Aw�;�� ��Ba�J%�ޓ���;�����с� ���4�2�<xͩt�8��="" p�ٴi�����="" 4g�q8��:��u�9q:v�i��x(���r�b��m��n��f�ml���="" ���)��n�="" ="" -��="" ���o����+�itj�_⧟~"Ȣ="" Ԯj��`�!�x��sn��n�g��'�j��cmv��o="" !�����?������޷r���p��(��)�,Ԭ^�z�0k֬���ŀh�`�5�'��1�����&\��+�2�o="" �v��4�="" �ac="" ��="" 4�f+�e�="" �ӭ�w����j���q�#�)��t̟??��x4�7e���oh�6o޼���r&�lh�z�n��l�8��pn���kἎbhj�e�-�|!�*���ɪ��z="">�E��Ŵ��;���Ʃ�0����j\�]o^�X�A�qο�8cVh�Q�M�x��F](L3�#'f�T�*4�IxZ,K8��͜ ! ���S��MJ�h� 5��2��p�!��wۇ�n� �M�/Z�c�=&Q��_h&�8� �X8��.��鑪&uRL���b�j�~Wg���A �d#MUG(�+�B_r�$�h�w ���i 2���ʠ>�QƸ�v�e�n�~|�fm�1� D��6K�w{����z��7T0�����}���ĩ#��Q�8K�Q�"�8�^2��d�N�+l�$j3�j����h'�x�V.��qmA�����P�?[� ^bIFE�Q����#�{i���o��� �:�<&��Y���Ѳ%�L�U��܍�����ź�ZB�\���*N��X� G!*=w�J#-���k5� m��\ 7�8O~��,��=�݄}Jp�?�P�L)�P��j4F�����"Ds:��I�o���^{M����*4H#�
And I used this code for downloading
$fn = $path.'/'.$file_name;
$mm_type="application/octet-stream";
header("Cache-Control: public, must-revalidate");
header("Pragma: hack");
header("Content-Type: " . $mm_type);
header("Content-Length: " .(string)(filesize($fn)) );
header('Content-Disposition: attachment; filename="'.$file_name.'"');
header("Content-Transfer-Encoding: binary\n");
readfile($fn);
I have tried with your code and found no problem. After read your comment and try with your file thetexturemill.com/wp-content/uploads/2013/07/dell.png I have this code working:
# my demo value in my local machine
$path = dirname(__FILE__) . "/demo";
$file_name = "Capture.PNG";
#$fn = realpath($path.'/'.$file_name);
$fn = "http://thetexturemill.com/wp-content/uploads/2013/07/dell.png";
//var_dump(readfile($fn));
$mm_type="application/octet-stream";
#$mm_type=mime_content_type($fn);
#echo $mm_type; die();
ob_get_flush();
header("Cache-Control: public, must-revalidate");
header("Pragma: hack");
header("Content-Type: " . $mm_type);
#header("Content-Length: " .(string)(filesize($fn)) );
header('Content-Disposition: attachment; filename="'.$file_name.'"');
header("Content-Transfer-Encoding: binary\n");
readfile($fn);
flush();
die();
What problems I found are:
If you use an image from remote host, make sure you can get it (the allow_url_fopen INI option is ON and the returned value from readfile is greater than zero) and do not use filesize as well as mime_content_type functions.
I don't know whether thetexturemill.com is your domain name or folder name. Supposed that it is a domain name, remember to add the protocal prefix (http:// as in example)
Do not output anything before the header function calls or your downloaded file will not be open properly.
Ah, for local file, your original code work without errors on my machine.
The content type is wrong
application/octet-stream
Ocet-stream is used for executable files which images are not for sure.
A proper type for a image for jpg image is for example:
image/jpeg
You can use mime_content_type() to get proper content type of file
Returns the MIME content type for a file as determined by using information from the magic.mime file.
Try this code
$fn = $path.'/'.$file_name;
$mime = mime_content_type($fn);
header('Content-Type:'.$mime);
header('Content-Length: ' . filesize($fn));
readfile($fn);
Try this,
<?php
$fn = $path.'/'.$file_name;
$mm_type="application/octet-stream";
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header("Content-Length: " .(string)(filesize($fn)) );
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Disposition: attachment; filename="'.$fn.'"');
header("Content-Transfer-Encoding: binary\n");
ob_clean();
flush();
readfile($fn);
exit;
?>
Read this http://php.net/manual/en/function.readfile.php

Download File in Yii

I am trying to write a script in Yii for downloading files from the server.
The files are located in webroot of the Yii project,
but I got every time file not exist error, could anyone see where is wrong:
public function actionDownload($id) {
$audio = Audio::model()->findByPk($id);
$file = Yii::getPathOfAlias('webroot') . $audio->path;
if (file_exists($file)) {
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename=' . $audio->path);
header('Content-Length: ' . filesize($audio->path));
$audio->downloaded = $audio->downloaded + 1;
$audio->save();
}else{
echo "file not exist: ".$file;
}
exit;
}
error I got is:
file not exist: /var/www/vhosts/ikhwanbiz.org/httpdocs/userfiles/reklames/media/deneme/sen%20dep%20olmisem.mp3
Thanks
Regards
Bili
Bili, this works well for me and seem to be fine on most browsers.
$filename = 'your_file_name.csv';
header('Content-Disposition: attachment; charset=UTF-8; filename="'.$filename.'"');
$utf8_content = mb_convert_encoding($content, "SJIS", "UTF-8");
echo $utf8_content;
Yii::app()->end();
return;
Hope it helps, good luck!
It looks like the filename portion $audio->path is URL-encoded, while the name of the actual file on the server is not. You should fix it at the source (no idea where that path is set from), but in the meantime an easy workaround would be to write
$file = Yii::getPathOfAlias('webroot') . urldecode($audio->path);
This is more of a php question than a yii one.
for eg,
<?php
header("Content-disposition: attachment; filename=huge_document.pdf");
header("Content-type: application/pdf");
readfile("huge_document.pdf");
?>
source: http://webdesign.about.com/od/php/ht/force_download.htm

try to download file and getting invalid file in response in core php

I download a file but it gives invalid file in return.
Here's my download_content.php
<?php
$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");
/* 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;
?>
download file link:
Download
$r['file'] contains the file name to be downloaded.
The complete path of the folder which contain the file is:
localhost/ja/gallery/downloads/poster/large/'.$r['file'].'
ja is the root folder in htdocs.
I don't know what the actual problem is, can anyone help me out please?
<?php
header( "Content-Type: application/vnd.ms-excel" );
header( "Content-disposition: attachment; filename=spreadsheet.xls" );
// print your data here. note the following:
// - cells/columns are separated by tabs ("\t")
// - rows are separated by newlines ("\n")
// for example:
echo 'First Name' . "\t" . 'Last Name' . "\t" . 'Phone' . "\n";
echo 'John' . "\t" . 'Doe' . "\t" . '555-5555' . "\n";
?>
As said in the other question, this way looks better:
$filename = $_GET["filename"];
// Validate the filename (You so don't want people to be able to download
// EVERYTHING from your site...)
// For example let's say that you hold all your files in a "download" directory
// in your website root, with an .htaccess to deny direct download of files.
// Then:
$filename = './download' . ($basename = basename($filename));
if (!file_exists($filename))
{
header('HTTP/1.0 404 Not Found');
die();
}
// A check of filemtime and IMS/304 management would be good here
// Google 'If-Modified-Since', 'If-None-Match', 'ETag' with 'PHP'
// Be sure to disable buffer management if needed
while (ob_get_level()) {
ob_end_clean();
}
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.
UPDATE: apparently the file is not found, which means that the filename= parameter to the PHP script is wrong (refers a file that's not there). Modified the code above to allow a directory to contain all files, and downloading from there.
Your $filename variable contains whole path as below
header("Content-Disposition: attachment; filename=$filename");
Do like this
$newfilename = explode("/",$filename);
$newfilename = $newfilename[count($newfilename)-1];
$fsize = filesize($filename);
Then pass new variable into header
header("Content-Disposition: attachment; filename=".$newfilename);
header("Content-length: $fsize");
//newline added as below
ob_clean();
flush();
readfile($filename);

Categories