Downloading code is not working in wordpress [duplicate] - php

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

Related

readfile() function read the zip file instead of Downloading it (Zend)

I have to trigger a download of a zip file ( The Zip file is inside my data folder).
For this i am using the code,
$file = 'D:\php7\htdocs\Project\trunk\api\data\file.zip';
header('Content-Description: File Transfer');
header('Content-type: application/zip');
header('Content-disposition: attachment; filename=' . basename($file) );
readfile($file);`
This is working in core php as i expected. But when i am using the same code in the Zend prints a content like below,
PKYsVJ)~�� study.xlsPKYsVJs�����+
tutorial-point-Export.xlsPKYsVJn��� 8��Zabc.xlsP
In between the content i can see the name of all files in the zip. But it is not getting downloaded.
After i realised that this is not working i started searching about it and Found some solution from stack over flow
Try 1: Adding different header element and ob functions in every random lines
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: ' . $file_size);
ob_start();
ob_clean();
flush();
All these are tried from different stack overflow Question and answers and have the same result
Try 2:PHP is reading file instead of downloading . This question do not have any accepted answer (He was asking about the core php but i have the same issue with zend only) . I tried all of this but it was not working.
Try 3:Changing the .htaccess . After that i thought it was a problem with my .htaccess and found this answer for changing the .htaccess file.
<FilesMatch "\.(?i:zip)$">
ForceType application/octet-stream
Header set Content-Disposition attachment
</FilesMatch>
This also given me the same result.
Try 4:Using download functions in Zend . I have tried the all the zend functions in the answer of this question. But given me an empty output even the file was not read.
Try 5: Remove all the unwanted spaces before and after the php tag as per the answer
Is there any other way to trigger a download in ZF2 framework?
EDIT
Below is my exact function. This is GET(API) function,
public function getList(){
try{
//here i am getting the zip file name.
$exportFile = $this->getRequest()->getQuery('exportid','');
$file = 'D:\php7\htdocs\Project\trunk\api\data\\' . $exportFile . '.zip';
header('Content-Description: File Transfer');
header('Content-type: application/zip');
header('Content-disposition: attachment; filename=' . basename($file) );
readfile($file);
return new JsonModel(["status"=>"Success"]);
} catch(\Exception $e){
return new JsonModel(["status"=>"Failed"]);
}
}
There are two problems here:
your browser trying to open the file, instead of downloading it.
also, it is not opening the file correctly.
Both point to a Content-Type error. Verify that the Content-Type being received by the browser is correct (instead of being rewritten as, say, text/html).
If it is, change it to application/x-download. This might not work in Internet Explorer, which performs some aggressive Content-Type sniffing. You might try adding a nosniff directive.
Additionally, after a readfile (and you might be forced to return the file's contents instead of readfile()'ing - i.e., return file_get_contents($filename);), you should stop all output with return null;. ZIP file directory is at the very end, so if you attach a JSON message there, you risk the browser neither downloading the file, nor displaying it correctly.
As a last resort, you can go nuclear and do everything yourself. Extremely non-elegant, and all frameworks ought to provide an alternative, but just in case...
// Stop *all* buffering
while (ob_get_level()) {
ob_end_clean();
}
// Set headers using PHP functions instead of Response
header('Content-Type: application/x-download');
header('X-Content-Type-Options: nosniff');
header('Content-Length: ' . filesize($filename));
header('Content-Disposition: attachment; filename="whatever.zip"');
die(readfile($filename));
It's possible that some creative use of atexit handlers or destructor hooks might mess up even this last option, but I feel it's unlikely.
Based on this SO answer, you can try the following modification to your function.
public function getList(){
try{
//here i am getting the zip file name.
$exportFile = $this->getRequest()->getQuery('exportid','');
$file = 'D:\php7\htdocs\Project\trunk\api\data\\' . $exportFile . '.zip';
if (file_exists($file)) {
$response = new \Zend\Http\Response\Stream();
$response->setStream(fopen($file, 'r'));
$response->setStatusCode(200);
$response->setStreamName(basename($file));
$headers = new \Zend\Http\Headers();
$headers->addHeaders(array(
'Content-Description' => 'File Transfer',
'Content-Disposition' => 'attachment; filename="' . basename($file) .'"',
'Content-Type' => 'application/zip',
'Content-Length' => filesize($file)
));
$response->setHeaders($headers);
return $response;
//return new JsonModel(["status"=>"Success"]);
} else {
return new JsonModel(["status"=>"Failed. No such file in \"".$file."\""]);
}
} catch(\Exception $e){
return new JsonModel(["status"=>"Failed"]);
}
}
This worked for me!
ob_clean(); // Clear any previously written headers in the output buffer
$filepath = "some_file.zip";
$content_type = 'application/octet_stream';
$filetype = filetype($filepath);
$filename =$filepath;
if($filetype=='application/zip')
{
if(ini_get('zlib.output_compression'))
ini_set('zlib.output_compression', 'Off');
$fp = #fopen($filepath, 'rb');
if (strstr($_SERVER['HTTP_USER_AGENT'], "MSIE"))
{
header('Content-Type: '.$content_type);
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: ".filesize(trim($filepath)));
}
else
{
header('Content-Type: '.$content_type);
header('Content-Disposition: attachment; filename="'.$filename.'"');
header("Content-Transfer-Encoding: binary");
header('Expires: 0');
header('Pragma: no-cache');
header("Content-Length: ".filesize(trim($filepath)));
}
fpassthru($fp);
fclose($fp);
}
If you correct the capitalisation of the headers does it work? ie use Content-Disposition and Content-Type over Content-disposition and Content-type respectively?
Regardless, as standard debugging technique I would suggest using your browser dev tools to inspect the requests that are being made (inc headers) and comparing that to what ends up in your serverside code, and what is in the server side response and what ends up in the client. I would also validate this using a private-session (Incognito mode in Chrome etc) or a fresh profile / VM install just to eliminate anything else.
Also, why not use xsendfile and delegate the responsibility of sending the file to the web server so you aren't incurring the responsibility in your PHP code? You can do this with appropriate server configuration (sometimes through .htaccess, but in this day and age surely you have complete control anyway) and then simply setting the X-Sendfile header as per the example on the above link:
header("X-Sendfile: $path_to_somefile");
header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename=\"$somefile\"");
Because you are return JsonModel so your output will be a json with your message instead of buffering for downloading.
Edit: I notice that you was missing Content-Transfer-Encoding: Binary, tested on my os x - php5.6 env.
You should try this
public function getList(){
try{
//here i am getting the zip file name.
$exportFile = $this->getRequest()->getQuery('exportid','');
$file = 'D:\php7\htdocs\Project\trunk\api\data\\' . $exportFile . '.zip';
header('Content-Description: File Transfer');
header('Content-type: application/zip');
header('Content-disposition: attachment; filename=' . basename($file));
header("Content-Transfer-Encoding: Binary");
header("Content-length: " . filesize($file));
header("Pragma: no-cache");
header("Expires: 0");
readfile("$file");
} catch(\Exception $e){
return new JsonModel(["status"=>"Failed"]);
}
}
Just remove your JSonModel on response.
You can try this for downloading the file instead of readfile();
Server side -
file_put_contents("file.zip", fopen("http://someurl/file.zip", 'r'));
Client side -
<button>download file</button>
download 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);

downloading issue in php .. return invalid file? [duplicate]

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.

serving .docx files through my webserver are corrupt when opened

i though i found the answer here:
Serving .docx files through Php
But i am still getting the error that the file is corrupt when trying to download and open a docx server via php
Maybe you can see something wrong with my code. The .doc works fine it is the docx that fail.
$parts = pathinfo($doc);
$docFile = $userDocRoot.$doc;
if ( !file_exists($docFile) ){
throw new Exception("Can not find ".$parts ['basename']." on server");
}
if ( $parts['extension'] == 'docx' ){
header('Content-type: application/vnd.openxmlformats- officedocument.wordprocessingml.document');
header('Content-Disposition: attachment; filename="'.$parts['basename'].'"');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
ob_clean();
flush();
readfile($docFile);
}else{
header('Content-type: application/msword');
header('Content-Disposition: attachment; filename="'.$parts['basename'].'"');
readfile($docFile);
}
The solution for me was to add
$fsize = filesize($docFile);
header("Content-Length: ".$fsize);
Thanks for everyones help
There were a few extra spaces in your code which would cause it to fail.
Try using this code:
$parts = pathinfo($doc);
$docFile = $userDocRoot . $doc;
if(!file_exists($docFile)){
throw new Exception('Can not find ' . $parts['basename'] . ' on server');
}
if($parts['extension'] == 'docx') {
header('Content-type: application/vnd.openxmlformats-officedocument.wordprocessingml.document');
header('Content-Disposition: attachment; filename="' . $parts['basename'] . '"');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
ob_clean();
flush();
readfile($docFile);
} else {
header('Content-type: application/msword');
header('Content-Disposition: attachment; filename="' . $parts['basename'] . '"');
readfile($docFile);
}
If it still doesn't work, try commenting out the header and the readfile lines, then you will see if there are any errors.
Also, I suggest that you check the filenames against a whitelist, so that people can't download PHP files with passwords in them, etc.
I have just spent a while looking at why my DOCX files are being corrupted and stumbled across this... but I have also found the answer elsewhere...
$fsize = filesize($docFile);
header("Content-Length: ".$fsize);
This gave me the tools to look for... and the key is that filesize() needs the basename of the file to get an accurate file size!
Adapting my code:
header("Content-Length: ".filesize(basename($file)));
This now offers DOCX (I have set the Content-type to "application/vnd.openxmlformats-officedocument.wordprocessingml.document") as intended and I do not have to "repair" the document like others have reported... (I also found that repairing worked)
Here is a code that's working for me (after about 5 hours of messing around):
// headers to send your file
header('Content-Type: application/vnd.openxmlformats-officedocument.wordprocessingml.document');
header("Content-Length: " . filesize($original_file));
header('Content-Disposition: attachment; filename="' . $new_filename . '"');
ob_clean();
flush();
readfile($original_file);
exit;
I hope it helps :)
I had the same issue.
The reason was, that somewhere in my php-file two spaces were hidden.
Removing them fixed the issue.
Add "//" in front of the header and readfile-statements
Write echo "test"; after the readfile-statement.
Then look in the HTML source-code, if there are spaces in front of
the "test".

Download Image link using php

I downloaded this code to use as a download button.
<?
$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;
?>
The thing is, the name of the file ends up with the whole path in the file name, for example, this code:
<a href="download.php?filename=images/something.jpg">
Ends up with an image named "images_something.jpg"
I'd like to remove the "images_" from the final file name, so far I haven't had any luck.
Thanks for the help!
If you need the file name part without folder name, you have to use basename($filename)
http://php.net/manual/en/function.basename.php
basename()
$filename = basename($path);
p.s
Setting Content-Type several times may not be the best way to force a download. Also, I hope you're sanitizing that $filename argument before you use a file_get_contents.
p.p.s
Use readfile, don't cache it in the memory.
$filename = basename($filename);
header("Content-Disposition: attachment; filename=$filename");
Set your filename to only be the basename?
Don't do it at the top unless you change the variables though so your pathing to it still works.

Categories