Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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"]);
    }
}
like image 565
Prifulnath Avatar asked Feb 23 '17 11:02

Prifulnath


People also ask

What does ReadFile do in PHP?

Definition and Usage. The readfile() function reads a file and writes it to the output buffer. Tip: You can use a URL as a filename with this function if the fopen wrappers have been enabled in the php.ini file.

What is the use of readfileex?

Reads data from the specified file or input/output (I/O) device. Reads occur at the position specified by the file pointer if supported by the device. This function is designed for both synchronous and asynchronous operations. For a similar function designed solely for asynchronous operation, see ReadFileEx.

What is ReadFile function in C++?

ReadFile function. Reads data from the specified file or input/output (I/O) device. Reads occur at the position specified by the file pointer if supported by the device. This function is designed for both synchronous and asynchronous operations.

How to lock a read in Zend Framework?

If you need a locked read, use fopen (), flock (), and then fpassthru () directly. That is one way to do it, however this is avoidable. For example in Zend Framework you could do $response->setBody('Sorry, we could not find requested download file.');


1 Answers

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.

like image 66
LSerni Avatar answered Oct 21 '22 09:10

LSerni