1

I have created php script to allow user to download zip files. Script looks like:

$filePath = '/path/to/zipfile.zip'; // file is below /public_html/ directory

if(file_exists($filePath)) {
    $fileName = basename($filePath); 
    $fileSize = filesize($filePath); //returns: 26494938

    header("Content-Type: application/zip");
    header("Content-Length: ".$fileSize);
    header("Content-Disposition: attachment; filename=".$fileName);

    readfile($filePath);                            
    die;    
};

I would expect this script to pass zipfile.zip for downloading. And it does, the save dialog pops up, I am choosing where to save, pressing save and zip file saves. Except one important thing - the file is with 0 bytes, it is completely empty zip file. Original zip file is full with files (around 25Mb). Maybe the size is the problem?

Can someone please help with some advice? Path to file is correct. I suspect that the problem is most likely related to readfile() function and/or zip file size, if so is there some alternative to readfile() that would work? Thank you!

Update: I have tried to use function readfile_chunked as mentioned in this post: "Readfile reads 0 bytes from large file?" - the result is that zip after downloading now have some size (no longer 0 bytes) and all correct content inside it, looks like everything is ok, but the zip is invalid, and cannot be unzipped and opened normally. In Win8 when trying to open downloaded zip file I am receiving this error: The Compresed (zipped) Folder zipfile.zip is invalid.. Of course the original zip file works fine. WinRAR shows this error: zipfile.zip: Unexpected end of archive. It looks the same problem as described in this post, without any working solution.

Community
  • 1
  • 1
wzazza
  • 803
  • 2
  • 11
  • 19
  • What permissions the file have? – zerkms Nov 23 '14 at 00:55
  • @zerkms full permissions> Also thought about that, permissions is not a problem. – wzazza Nov 23 '14 at 00:57
  • How many bytes does `readfile()` actually read? Can you log the return value? Are there any messages in the error log? – Nisse Engström Nov 23 '14 at 01:09
  • @NisseEngström Thanks for your replay. `readfile()` actually returns nothing or 0 bytes. Tried to check with some other file and the function returned value, it is with `zip` it returns nothing. And about error log - no unfortunately there are no error messages. – wzazza Nov 23 '14 at 01:23
  • It's most likely a path issue. I tested your code and it worked fine. Put a zip file you know is good inside the same folder as the script you're running from and change `$filePath = '/path/to/zipfile.zip';` to `$filePath = 'zipfile.zip';` and it should work. You will then need to figure out why the path to the file is not being found. – Funk Forty Niner Nov 23 '14 at 03:04
  • @Fred-ii- No this is not path issue. Have you tried with 26Mb zip file does the script works then for you? I think the problem is size. About path I already mentioned in initial post, but still rechecked with the same folder as you suggested, this doesn't help, so this is not path issue. – wzazza Nov 23 '14 at 09:05
  • Try increasing the file size settings in your .ini file. – Funk Forty Niner Nov 23 '14 at 12:54
  • @Fred-ii- Thanks, memory setting somehow helped, the file is no longer 0 bytes with `readfile()`, but still the downloaded zip is invalid. It cannot be opened or extracted normally the same as with `readfile_chunked()` function I mentioned in post update. – wzazza Nov 23 '14 at 14:27
  • You're welcome. See this Q&A http://stackoverflow.com/q/2184513/ if you haven't seen it yet, or have the same settings in your .ini file. Also trying `header ('Content-length: '.filesize($fileSize));` instead of `$fileSize = filesize($filePath);` – Funk Forty Niner Nov 23 '14 at 14:30

2 Answers2

2

Try to add ob_end_flush(); before readfile($filePath); . It

  • Whilst this may theoretically answer the question, [it would be preferable](//meta.stackoverflow.com/q/8259) to include the essential parts of the answer here, and provide the link for reference. – Enamul Hassan May 03 '16 at 00:01
0

The simplest solution is to do away with the php completely, just provide an HTML link to the zip and let your server do the work

also if you really must stick with php to serve this, you have no code there that actually sends the file to the user, readfile doesn't do that it just loads it into the program

  • I cannot do it in project I am working with. Zip files are stored below /public_html/ folder, they have no public access. – wzazza Nov 23 '14 at 00:52
  • then you should restructure your project to put them there. As it is your script (if it worked) would allow the user to download any file on your disk. The reason that webservers are only supposed to serve things in their web root folder is because otherwise it leaves them open to attack – Mordax Praetorian Nov 23 '14 at 00:55
  • 1
    The script I posted is partial to whole system, this is responsible for file downloading. There are other security scripts that will prevent accessing any other files. Also the script works with any other file, for example `.txt` file. it is with `zip` that I have the problem. – wzazza Nov 23 '14 at 01:05
  • The `readfile()` function [**"Reads a file and writes it to the output buffer"**](http://php.net/manual/en/function.readfile.php), which is exactly what the OP wants. – Nisse Engström Nov 23 '14 at 01:06
  • so it does, my apologies it has been some time since I've done any php – Mordax Praetorian Nov 23 '14 at 01:13