Emil Borconi Emil Borconi - 1 year ago 67
PHP Question

Lighttpd X-Sendfile corrupted files

Can anybody give me a hint on what is wrong? I have a script which generates a ZIP file on the fly and then serve it for download using X-Sendfile and lighttpd. Everything seems to be working but my downloaded file is a few bytes less compared to the zip file created on the server, and of course because it's the header of the file which is missing it results in broken zip file.
Here is the relevant part of my script:

header("Content-Disposition: attachment; filename=\"$MYVARIABLE1" . ".zip\"");

if ($status == 1) {
$tmp_file = tempnam('/tmp/', '');
$dir = new RecursiveDirectoryIterator("/mnt/BLABLABLA/$MYVAR2/$MYVAR3/", FilesystemIterator::SKIP_DOTS);
$it = new RecursiveIteratorIterator($dir, RecursiveIteratorIterator::SELF_FIRST);
$mylist = "";
foreach ($result as $row) {
$files = new RegexIterator($it, "/" . $row[2] . "/", RegexIterator::GET_MATCH);
$mylist.="\"" . key(iterator_to_array($files)) . "\" ";
exec("/usr/bin/zip -qj0 $tmp_file $mylist");
header("X-LIGHTTPD-send-file: $tmp_file" . ".zip");

The zip on the server tmp folder is fine, but the downloaded content is corrupted.

Answer Source

After tinkering around for a while I found the solution, yet not sure what it caused it. I needed to set the file size header before actually passing the file to X-Sendfile, so the code looks like this now:

    exec("/usr/bin/zip -qj0 $tmp_file $mylist");
    header("Content-Length: ".filesize($tmp_file.".zip"));
    header("X-LIGHTTPD-send-file: $tmp_file" . ".zip");

However this is not specified as a requirement in the Lighttpd Wiki, so it might be a bug.

The problem was I had zlib.compression on and I was trying to send out a ZIP file which resulted in double compression. Turning off zlib.compression on runtime has fixed the issue.