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);
Related
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
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!
I am working on a project where I get a file stream and write this file to the servers local disk.
I then want PHP to download it but instead it just dumps out the data of the file to the page.
Below is how I am writing the file and trying to tell PHP to download it
$settingsManager = new SettingsManager();
$this->tempWriteLocation = $settingsManager->getSpecificSetting("hddFileWriterLocation");
$downloadUrl = $settingsManager->getSpecificSetting("tempFileUrlDownload") . "/$this->tempFileName";
if (!$this->checkIfDirectoryExists())
{
throw new Exception("Failed to create temp write directory: $this->tempWriteLocation");
}
$filePathAndName = "$this->tempWriteLocation\\$this->tempFileName";
$fh = fopen($filePathAndName, "w");
if (!$fh)
{
throw new Exception("Failed to open file handle for: $filePathAndName. " . error_get_last());
}
fwrite($fh, $this->fileData);
fclose($fh);
//return $downloadUrl;
header('Content-Description: File Transfer');
header('Content-Type: audio/wav');
header('Content-Disposition: attachment; filename='.basename($filePathAndName));
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($filePathAndName));
ob_clean();
flush();
readfile($filePathAndName);
When the above code being run, I get the following output (only a snippet)
RIFF\tWAVELIST2INFOISFT%Aculab Media System Server V2.3.4b11fmt
##fact�sdata�sUU������UUUUUU�UUU��U���UU��UUU�UUUU���UU���UU�����UU
Just so you know the diamonds are actual output I get back, not anything wrong with Stack Overflow displaying something properly.
I've tried setting the content-type to be force-download but doesn't make any difference.
Try this header:
header('Content-type: audio/x-wav', true);
header('Content-Disposition: attachment;filename=wav-filename.wav');
and see if this works. From what I see you have you code formation setup correctly. Fixing the headers should download the file automatically.
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
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;
}