Download image with Zend - PHP header: wrong file format - php

First of all, I know this question has already been asked but I can't solve it anyway.
I need to set a link to download images(jpg).
I read various posts found here and with google but it's always the same results:
I can download the file but it's still the same error. The jpeg format is not correct.
Erreur d'interprétation du fichier
d'image JPEG (Not a JPEG file: starts
with 0x0a 0x20)
When I test this in a file without a controller, it's ok but the script in a controller doesn't work.
Here is the code for tests:
$file = '{document_root}/www/themes/default/images/common/background1.jpg';
if (file_exists($file))
{
header('Content-type: application/octet-stream');
header('Content-Disposition: attachment; filename=' . basename($file));
header('Content-length: ' . filesize($file));
readfile($file);
exit;
}
This code works in a simple php file. I download the picture and can open it.
But within my controller, the file is not good.
I found that the tag ?> can add spaces but my controllers doesn't have this closing tag.
I've tested some code with the Zend objects found in various posts but it's the same error.
I've tried various way to read the file (file_get_content(), fread() ...) with the same result.
I assume there's something wrong with my Zend controller.
I'm now testing my file according to this post:
php file download: strange http header
Any clue will be really appreciated.
Thanks for your help and sorry for my bad english.
[EDIT: 21/06/2011 - 6h38]
Here is the code of the action
public function downloadAction()
{
$this->view->layout()->disableLayout();
$this->_helper->viewRenderer->setNoRender(true);
$img = $this->_getParam('img');
// Process the file
$config = Zend_Registry::get('config');
$width = $config->catalog->image->original->maxWidth;
$height = $config->catalog->image->original->maxHeight;
$prefix = $width . 'x' . $height . '_';
$filename = $prefix . $img;
$file = Zend_Registry::get('document_root') . '/data/images/catalog/products/' . $this->_getParam('pid') .'/'. $filename;
if (file_exists($file))
{
$this->getResponse()
->setHeader('Content-Disposition', 'attachment; filename='.$filename)
->setHeader('Content-Transfer-Encoding', 'binary')
->setHeader('Content-Length', filesize($file))
->setHeader('Content-type', 'image/jpeg');
$this->getResponse()->sendHeaders();
readfile($file);
exit;
}
}
This action is not called directly. I test if a parameter exists in the url.
If true then from the listAction, I call the downloadAction().
I've tried to disable the view and layout in both action but there's some html rendered.

I had the same problem sending content after decrypt file's content.
0x0a means new line. You probably have some new line after the ?> tag in some included class.
Put
ob_clean();
flush();
before
readfile($file);
something like this:
header('Content-type: application/octet-stream');
header('Content-Disposition: attachment; filename=' . basename($file));
header('Content-length: ' . filesize($file));
ob_clean();
flush();
readfile($file);
exit;
This work out fine for me. Hope it helps.
Regards

I codeing working zend framework :)
public function dowloadfileAction(){
$this->_helper->viewRenderer->setNoRender(true);
$this->_helper->layout->disableLayout();
if ($this->_user->isUserLogin()) {
$path_file = 'public/uploads/file/';
$filename = $this->_getParam('file');; // of course find the exact filename....
$file = $path_file.$filename;
//zfdebug(mime_content_type($file)); die();
if (file_exists($file)) {
header('Pragma: public');
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: '.mime_content_type($file));
header('Content-Disposition: attachment; filename="'. basename($file) . '";');
header('Content-Transfer-Encoding: binary');
header('Content-Length: ' . filesize($file));
readfile($file);
}else{
echo "File does not exist";
}
}else{
echo "Please Login";
}
exit;
}

Related

Error while downloading Image on server using PHP

I have written following code in my Yii framework controller. This code is working fine on my localhost but not working on server.
Can somebody please tell me whats wrong with the code
Following is my code which I have written in controller
public function downloadFile($dir,$file,$extensions=[]){
if(is_dir($dir)){
$path = $dir.$file;
if(is_file($path)){
$fileinfo=pathinfo($path);
$extension=$fileinfo["extension"];
if(is_array($extensions)){
foreach($extensions as $e){
if($e===$extension){
$size = filesize($path);
header('Content-Type: application/octet-stream');
header('Content-Length: '.$size);
header('Content-Disposition: attachment; filename='.$file);
header('Content-Transfer-Encoding: binary');
readfile($path);
return true;
}
}
}
}else{
echo"error";
}
}
}
public function actionDownload(){
if(Yii::$app->request->get('file')){
$this->downloadFile("media/offer/",Html::encode($_GET["file"]),["jpg","png"]);
}
}
You tagged yii2, but it's not yii2, its pure php.
How about use framework to do this?
public function actionFile($filename)
{
$storagePath = Yii::getAlias('#app/files');
// check filename for allowed chars (do not allow ../ to avoid security issue: downloading arbitrary files)
if (!preg_match('/^[a-z0-9]+\.[a-z0-9]+$/i', $filename) || !is_file("$storagePath/$filename")) {
throw new \yii\web\NotFoundHttpException('The file does not exists.');
}
return Yii::$app->response->sendFile("$storagePath/$filename", $filename);
}
Yii2 - sendFile()
^Change storagePath to your file directory.
And that's all, nothing more to do.
Replace this function with yours,
public function downloadFile($dir,$file,$extensions=[]){
if(is_dir($dir)){
$path = $dir.$file;
if(is_file($path)){
$fileinfo=pathinfo($path);
$extension=$fileinfo["extension"];
if(is_array($extensions) && in_array($extension, $extensions)){
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');
header('Pragma: public');
header('Content-Length: ' . filesize($path));
ob_clean();
flush();
readfile($path);
exit;
}
}else{
echo"error";
}
}
}
I just called this with following,
downloadFile("/var/www/html/", "test.php", ['php']);
and it worked for me.

PHP force download corrupt PDF file

I have gone through all articles on Stack Overflow and can't fix my issue. I am using following code:
$file = $_GET['url'];
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="'.basename($file).'"');
header('Content-Length: ' . filesize($file));
readfile($file);
exit;
The above mention code is downloading the file from the directly above the root and Yes it is downloading a PDF file but the file is only of 1KB size and not the original size. The $_GET['url'] is receiving ../dir/dir/filename.pdf in it. the filename is space in it as well. For security reason I cannot share the file name.
Please let me know where am I going wrong.
Please make sure you are using the web server path to access the file - for instance your path could be: /home/yourusername/public/sitename/downloads/<filename>, you should check first - to help you can run this at the top of your PHP script to find out the full path for the current script:
echo '<pre>FILE PATH: '.print_r(__FILE__, true).'</pre>';
die();
Only send the filename with the url using urlencode() and on the receiving PHP script use urldecode() to handle any character encoding issues.
See here: http://php.net/manual/en/function.urlencode.php
and here: http://php.net/manual/en/function.urldecode.php
So where you create your url:
Download File
And in your php script:
$file_base_path = '/home/yourusername/public/sitename/downloads/';
$file = urldecode($_GET['url']);
$file = $file_base_path . $file;
$file = $_GET['url'];
if (file_exists($file))
{
if (FALSE!== ($handler = fopen($file, 'r')))
{
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename($file));
header('Content-Transfer-Encoding: chunked'); //changed to chunked
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
//header('Content-Length: ' . filesize($file)); //Remove
//Send the content in chunks
while(false !== ($chunk = fread($handler,4096)))
{
echo $chunk;
}
}
exit;
}
echo "<h1>Content error</h1><p>The file does not exist!</p>";
I hope this helps you!

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

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".

PDF document error using Zend_Pdf

In magento1.7, I have tried something like below in my custom controller.
public function getPDF()
{
$imagePath=C:\Users\.........;
$image = Zend_Pdf_Image::imageWithPath($imagePath);
$page->drawImage($image, 40,764,240, 820);
.
.
.
$pdf->pages[] = $page;
$pdf->save("mydoc.pdf");
}
There's no error in it. It generates PDF with image but the PDF document is saved in magento folder instead in My downloads folder. After doing some research, I found some following chunk of lines and added them after $pdf->pages[] = $page;.
$pdfString = $pdf->render();
header("Content-Disposition: attachment; filename=myfile.pdf");
header("Content-type: application/x-pdf");
echo $pdfString;
Now it generates PDF in My Downloads folder. When I try to open it. It throws error saying : Adobe reader couldn't open myfile.pdf because it's not either a supported file type or because the file has been damaged............ Do this happens,when we try to open PDF document generated on localhost or there's some other reason. Please let me know, why this error occurs and also provide me a solution to resolve it.
your problem is probably due to calling both save() and render() together.
save() actually calls render(), the issue could be due to trying to render the PDF twice.
This is also a waste of resources, if you need to save the file it's probably best to just save the file first, and then serve this file directly to the user.
You can do this in plain old PHP (using passthru or readfile), although there's ways to do this inside Zendframework which are better you can look into :)
// .. create PDF here..
$pdf->save("mydoc.pdf");
$file = 'mydoc.pdf';
if (file_exists($file)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename($file));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
ob_clean();
flush();
readfile($file);
exit;
}
?>
if your code is inside a Magento Controller:
$this->getResponse()
->setHttpResponseCode(200)
->setHeader('Pragma', 'public', true)
->setHeader('Cache-Control', 'must-revalidate, post-check=0, pre-check=0', true)
->setHeader('Content-type', $contentType, true)
->setHeader('Content-Length', filesize($file))
->setHeader('Content-Disposition', 'attachment; filename="'.$fileName.'"')
->setHeader('Last-Modified', date('r'));
$this->getResponse()->clearBody();
$this->getResponse()->sendHeaders();
$ioAdapter = new Varien_Io_File();
if (!$ioAdapter->fileExists($file)) {
Mage::throwException(Mage::helper('core')->__('File not found'));
}
$ioAdapter->open(array('path' => $ioAdapter->dirname($file)));
$ioAdapter->streamOpen($file, 'r');
while ($buffer = $ioAdapter->streamRead()) {
print $buffer;
}
$ioAdapter->streamClose();
exit(0);

Categories