cypher
cypher

Reputation: 6992

Unzipping larger files with PHP

I'm trying to unzip a 14MB archive with PHP with code like this:

    $zip = zip_open("c:\kosmas.zip");
    while ($zip_entry = zip_read($zip)) {
    $fp = fopen("c:/unzip/import.xml", "w");
    if (zip_entry_open($zip, $zip_entry, "r")) {
     $buf = zip_entry_read($zip_entry, zip_entry_filesize($zip_entry));
     fwrite($fp,"$buf");
     zip_entry_close($zip_entry);
     fclose($fp);
     break;
    }
   zip_close($zip);
  }

It fails on my localhost with 128MB memory limit with the classic "Allowed memory size of blablabla bytes exhausted". On the server, I've got 16MB limit, is there a better way to do this so that I could fit into this limit? I don't see why this has to allocate more than 128MB of memory. Thanks in advance.

Solution: I started reading the files in 10Kb chunks, problem solved with peak memory usage arnoud 1.5MB.

        $filename = 'c:\kosmas.zip';
        $archive = zip_open($filename);
        while($entry = zip_read($archive)){
            $size = zip_entry_filesize($entry);
            $name = zip_entry_name($entry);
            $unzipped = fopen('c:/unzip/'.$name,'wb');
            while($size > 0){
                $chunkSize = ($size > 10240) ? 10240 : $size;
                $size -= $chunkSize;
                $chunk = zip_entry_read($entry, $chunkSize);
                if($chunk !== false) fwrite($unzipped, $chunk);
            }

            fclose($unzipped);
        }

Upvotes: 6

Views: 7261

Answers (4)

elad
elad

Reputation: 21

function my_unzip($full_pathname){

    $unzipped_content = '';
    $zd = gzopen($full_pathname, "r");

    while ($zip_file = gzread($zd, 10000000)){
        $unzipped_content.= $zip_file;
    }

    gzclose($zd);

    return $unzipped_content;

}

Upvotes: 1

Quamis
Quamis

Reputation: 11087

Why do you read the whole file at once?

 $buf = zip_entry_read($zip_entry, zip_entry_filesize($zip_entry));
 fwrite($fp,"$buf");

Try to read small chunks of it and writing them to a file.

Upvotes: 5

Anax
Anax

Reputation: 9382

For a file of that size, perhaps it is better if you use shell_exec() instead:

shell_exec('unzip archive.zip -d /destination_path');

PHP must not be running in safe mode and you must have access to both shell_exec and unzip for this method to work.

Update:

Given that command line tools are not available, all I can think of is to create a script and send the file to a remote server where command line tools are available, extract the file and download the contents.

Upvotes: 1

46bit
46bit

Reputation: 1537

Just because a zip is less than PHP's memory limit & perhaps the unzipped is as well, doesn't take account of PHP's overhead generally and more importantly the memory needed to actually unzip the file, which whilst I'm not expert with compression I'd expect may well be a lot more than the final unzipped size.

Upvotes: 1

Related Questions