Search code examples
phpsymfony1zipcorrupt

Corrupted ZipArchive after setContent() in php symfony


I have a real strange behavior when sending a zip archive containing a any type of file in symfony. The problem is that the zip file, that I download from the browser contains an extra 'bit' at the beginning of the file.

Here's my code:

$tmpFileName = tempnam("/tmp", "xb_");
$zip = new ZipArchive();
$zip->open($tmpFileName, ZipArchive::CREATE);
$zip->addFile('[directory_inside_webspace]/test.pdf', 'myTest.pdf');
$zip->close();
$this->getResponse()->clearHttpHeaders();
$this->getResponse()->setContent(file_get_contents($tmpFileName));
$this->getResponse()->setHttpHeader('Content-Type', 'application/zip');
$this->getResponse()->setHttpHeader('Content-Disposition', 'attachment; filename=archive.zip');
return sfView::NONE;

Now here's what is strange. The temporary zip file under /tmp is fine. I can extract it without any problems. But the file the browser sends to me is corrupt. When I open both of them in hex editor, the first few bytes look like:

working file:      50 4B 03 04 14 00 00 
corrupt file:   0A 50 4B 03 04 14 00 00

When I remove the addition '0A' from the corrupt file I can open it without problems. It's now the exactly same file as the tmp file created in /tmp.

Did anyone had a behavior like this before?? I'm stucked at this problem for over 4 days now and I'm not able to find the error. I use exactly the same code in another symfony module and it's working in there. Any ideas ?

-----Update------

The problem wasn't related to the zipArchive or setContent. I had a query at the beginning of the function.

$bill = Doctrine::getTable('Bill')->find($request->getParameter('id'));

In the class 'Bill.class.php' in my doctrine model I had a blank line before

<?php

So when the class Bill was instantiated the new line was print to screen.

I just wonder why php doesn't give an error message like 'headers already send' when sending the zip Archive to the browser.


Solution

  • 0A is a newline character. Make sure there's no newline before the <?php tag of all the files involved, and no newline after the ?> tag (unless you omit the closing tag, which is recommended).
    The most probable culprit is the actions.class.php of the download action.