Rodster001 has asked for the wisdom of the Perl Monks concerning the following question:

Greetings! I am using IO::Compress::Zip but I cannot get the syntax quite right for what I am trying to do. Here is some pseudo code:

use IO::Compress::Zip qw(zip $ZipError); my $zip = new IO::Compress::Zip \*STDOUT or print STDERR "IO::Compress::Zip failed: $ZipError\n"; foreach my $file (@files) { ... do some stuff to the file ... now add file to the archive } $zip->close;

My problem: Using this the OO way I am not quite sure how to define the filename AND the contents of the file on each loop thus producing a stream to STDOUT with multiple files.

UPDATE

I ended up using Archive::Zip::SimpleZip. This seems to work good and does in fact stream the zip file from the server as it is being processed.

## when using '-', Stream is set to 1 my $z = new Archive::Zip::SimpleZip '-', or print STDERR "Cannot create zip file: $SimpleZipError\n"; foreach my $file (@files) { ... do some stuff to the file my $fh = $z->openMember(Name => "<filename.ext>"); print $fh <stuff>; close($fh); } $z->close;

Replies are listed 'Best First'.
Re: Multi file stream with IO::Compress::Zip
by NetWallah (Canon) on Sep 17, 2014 at 05:03 UTC
    I havent used this interface, but it looks like the syntax you need is :
    # Possibly, need to set binmode... $zip->newStream(name=>"SomeFileName.txt" ); # in a loop .. write data using: $zip->write $data, $length, $offset; # Then finally $zip->close; # Or do newStream for some other file name..

            "You're only given one little spark of madness. You mustn't lose it."         - Robin Williams

      What I couldn't figure out is how to specify a new (change of) filename. But see my update above, I went with a different module and it does what I need.

        If a streamed Zip file with multiple members is what you need then Archive::Zip::SimpleZip is probably the best way to go.

        I see in your code you've used '-' to force streaming. You can explicitly request streaming to a file/buffer by specifying the Stream option, as shown below. If writing to STDOUT is what you need, then you don't need to explicitly set it.

        ## Explicitly ask for Stream is set to 1 my $z = new Archive::Zip::SimpleZip "somefile.zip, Stream => 1 or print STDERR "Cannot create zip file: $SimpleZipError\n";

        FYI - I wrote Archive::Zip::SimpleZip because the interface I provided in IO::Compress::Zip to create a Zip file with multiple members is not the easiest to use. Archive::Zip::SimpleZip is just a wrapper around IO::Compress::Zip to make this use-case as easy as possible.

Re: Multi file stream with IO::Compress::Zip
by Rozman (Initiate) on Sep 22, 2017 at 06:00 UTC

    This is what I created and works for me. When user opening some URL on my page I am creating ZIP archive on the fly and sending it to user.

    If change "-" to "file.zip" it will save archive into your hosting/server (and don't need print "content type").

    use IO::Compress::Zip qw(:all); my @files = ('example.gif', 'example1.png', 'example2.jpg', 'exampl +e3.avi', 'example4.mov'); my $path = "/home/********/**********"; print "Content-Type:application/zip\n"; print "Content-Disposition: attachment; filename=\"filename.zip\"\n +\n"; my $z; foreach my $file (@files) { if ($z) { $z->newStream(Name => $file, Method => ZIP_CM_STORE); } else { $z = new IO::Compress::Zip "-", Name => $file, Method => ZIP_ +CM_STORE; } open(FILE, "<", "$path/$file"); binmode FILE; my ($buf, $data, $n); while (($n = read FILE,$data, 1024) != 0) { $z->print($data); } close(FILE); } $z->close; exit;