user371254
user371254

Reputation: 1

Zip Stream in PHP

I have a PHP script that creates a zip file on the fly and forces the browser to download the zip file. The question is: could I directly write the zip file to an output stream which is connected to the user's browser rather than save it as a real file on the server first and then send the file?

Thanks in advance.

Upvotes: 23

Views: 37851

Answers (5)

weasel5i2
weasel5i2

Reputation: 119

If your web server is running Linux, then you can do it streaming without a temp file being generated. Under Win32, you may need to use Cygwin or something similar.

If you use - as the zip file name, it will compress to STDOUT. That can be redirected straight to the requester using passthru(). The -q argument simply tells zip to not output the status text it normally would. See the zip(1) manpage for more info.

$zipfilename = 'zip_file_name.zip';

$files = array();

$target = '/some/directory/of/files/you/want/to/zip';

$d = dir( $target );

while( false !== ( $entry = $d->read() ) )
{
    if( substr( $entry, 0, 1 ) != '.' && !is_dir( $entry ) ) 
    {
        $files[] = $entry;
    }
}

if( ! $files )
{
    exit( 'No files to zip.' );
}

header( 'Content-Type: application/x-zip' );
header( "Content-Disposition: attachment; filename=\"$zipfilename\"" );

$filespec = '';

foreach( $files as $entry )
{
    $filespec .= ' ' . escapeshellarg( $entry );
}

chdir( $target );

passthru( "zip -q -$filespec" );

Upvotes: 16

Andreas Gohr
Andreas Gohr

Reputation: 4945

This library seems to be what you're looking for: https://github.com/maennchen/ZipStream-PHP

Upvotes: 14

Artur Grigio
Artur Grigio

Reputation: 5553

Yes, you can directly stream the zip to the client using this git rep: Zip Stream Large Files

Upvotes: 1

Artefacto
Artefacto

Reputation: 97845

No, you have to use a temporary file, as in here.

Upvotes: -2

Charles
Charles

Reputation: 51421

If you're using the zip extension, the answer seems to be "no." The close method in the ZipArchive class is what triggers a write, and it seems to want to write to a file. You might have some luck using Streams to simulate a file, but then you're keeping the entire thing in memory, and you still couldn't send it until you're done adding files.

If you're having problems with timeouts or other problems while having a user wait for the zip file to be created, try a multi-step download process:

  1. User picks whatever they pick to create the zip
  2. They're taken to a status page that uses ajax calls to actually build the zip file in the background. A pretty, distracting animation should keep their attention.
  3. After the background processes build the zip, the user is redirected to a script that performs the download / redirected to the file.

Upvotes: 5

Related Questions