Archive...impleZip(3)

๐Ÿ“ฆ
version 1.002 ยท 4 versions
, in fedora 43

omg bestie, you found the manual for Archive::Zip::SimpleZip(3) โ€” User Contributed Perl Documentation, and it's literally the blueprint for creating Zip archives like a main character ๐Ÿ’…โœจ. No cap, this module is iconic.


๐ŸŒธ NAME ๐ŸŒธ

Archive::Zip::SimpleZip โ€” Create Zip Archives โœจ

โœจ SYNOPSIS โœจ

use Archive::Zip::SimpleZip qw($SimpleZipError) ;

my $z = Archive::Zip::SimpleZip->('my.zip')
    or die "Cannot create zip file: $SimpleZipError\n" ;

$z->add('/some/file1.txt');
$z->addString("some text", Name => 'myfile');
$z->addFileHandle($FH, Name => 'myfile2') ;

$fh = $z->openMember(Name => 'mydata1.txt');
print $fh 'some data' ;
$fh->print('some more data') ;
close $fh;

$z->close();

๐Ÿ’– DESCRIPTION ๐Ÿ’–

Okay so Archive::Zip::SimpleZip is the module that lets you create Zip archives, bestie. For reading Zip archives, there's a companion module called Archive::Zip::SimpleUnzip that can read Zip archives. They're giving dynamic duo energy ๐Ÿฆธโ€โ™€๏ธ๐Ÿฆธโ€โ™€๏ธ.

The module allows Zip archives to be written to a named file, a filehandle, or stored in-memory. There are a small number methods available in Archive::Zip::SimpleZip, and quite a few options, but for the most part all you need to know is how to create a Zip archive and how to add a file to it. Lowkey simple, highkey powerful. ๐Ÿ’…

Below is an example of how this module is used to add the two files file1.txt and file2.txt to the zip file called my1.zip.

use Archive::Zip::SimpleZip qw($SimpleZipError) ;

my $z = Archive::Zip::SimpleZip->('my1.zip')
    or die "Cannot create zip file: $SimpleZipError\n" ;

$z->add('/some/file1.txt');
$z->add('/some/file2.txt');

$z->close();

The data written to a zip archive doesn't need to come from the filesystem. You can also write string data directly to the zip archive using the addString method, like this:

use Archive::Zip::SimpleZip qw($SimpleZipError) ;

my $z = Archive::Zip::SimpleZip->('my2.zip')
    or die "Cannot create zip file: $SimpleZipError\n" ;

my $myData = "some data";
$z->addString($myData, Name => 'file2.txt');

$z->close();

Alternatively you can use the openMember option to get a filehandle that allows you to write directly to the zip archive member using standard Perl file output functions, like print.

use Archive::Zip::SimpleZip qw($SimpleZipError) ;

my $z = Archive::Zip::SimpleZip->('my3.zip')
    or die "Cannot create zip file: $SimpleZipError\n" ;

my $fh = $z->openMember(Name => 'file3.txt');

$fh->print('some data');

print $fh 'more data' ;

$fh->close() ;
# can also use close $fh;

$z->close();

You can also drop an open filehandle that is open for reading into a zip archive. It's giving "here, hold my data" energy. ๐Ÿซถ

use Archive::Zip::SimpleZip qw($SimpleZipError) ;

my $z = Archive::Zip::SimpleZip->('my4.zip')
    or die "Cannot create zip file: $SimpleZipError\n" ;

open my $data, '<', 'somedata'
    or die "Cannot open 'somedata': $!\";

# drop the $data filehandle into the zip file, naming it 'file3.txt;
my $fh = $z->addFileHandle($data, Name => 'file3.txt');

$z->close();

๐Ÿงš Constructor ๐Ÿงš

$z = Archive::Zip::SimpleZip->new('myzipfile.zip' [, OPTIONS]) ;
$z = Archive::Zip::SimpleZip->new(\$buffer [, OPTIONS]) ;
$z = Archive::Zip::SimpleZip->new($filehandle [, OPTIONS]) ;

The constructor takes one mandatory parameter along with zero or more optional parameters. Periodt.

The mandatory parameter controls where the zip archive is written. This can be any of the following:

  • Output to a File โ€” When SimpleZip is passed a string, it will write the zip archive to the filename stored in the string. ๐Ÿ“ slay
  • Output to a String โ€” When SimpleZip is passed a string reference, like \$buffer, it will write the zip archive into that string. ๐Ÿงต
  • Output to a Filehandle โ€” When SimpleZip is passed a filehandle, it will write the zip archive to that filehandle. ๐Ÿ—‚๏ธ

Use the string '-' to write the zip archive to standard output (Note - this will also enable the Stream option). ๐Ÿ“บ

See "Options" for a list of the optional parameters that can be specified when calling the constructor.

๐Ÿ’… Methods ๐Ÿ’…

$z->add($filename [, OPTIONS])

The add method writes the contents of the filename stored in $filename to the zip archive.

The following file types are supported.

  • Standard files โ€” The contents of the file is written to the zip archive. ๐Ÿ“„
  • Directories โ€” The directory name is stored in the zip archive. ๐Ÿ“‚
  • Symbolic Links โ€” By default this module will store the contents of the file that the symbolic link refers to. To store the symbolic link itself set the StoreLink option to 1. ๐Ÿ”—

By default the name of the member created in the zip archive will be derived from the value of the $filename parameter. See "File Naming Options" for more details.

See "Options" for a full list of the options available for this method.

Returns 1 if the file was added, or 0. Check the $SimpleZipError for a message.

$z->addString($string, Name => "whatever" [, OPTIONS])

The addString method writes $string to the zip archive. The Name option must be supplied.

See "Options" for the options available for this method.

Returns 1 if the file was added, or 0. Check the $SimpleZipError for a message.

$z->addFileHandle($fh, Name => "whatever" [, OPTIONS])

The addFileHandle method assumes that $fh is a valid filehandle that is opened for reading.

It writes what is read from $fh to the zip archive until it reaches the eof. The filehandle, $fh, will not be closed by addFileHandle. ๐Ÿšซ๐Ÿ”’

The Name option must be supplied.

See "Options" for the options available for this method.

Returns 1 if the file was added, or 0. Check the $SimpleZipError for a message.

my $fh = $z->openMember(Name => "abc" [, OPTIONS]);

This option returns a filehandle ($fh) that allows you to write directly to a zip member. The Name option must be supplied. See "Options" for the options available for this method.

The filehandle returned works just like a standard Perl filehandle, so all the standard file output operators, like print, are available to write to the zip archive.

When you have finished writing data to the member, close the filehandle by letting it go out of scope or by explicitly using either of the two forms shown below:

$fh->close()
close $fh;

Once the filehandle is closed you can then open another member with openMember or use the add or addString or addFileHandle methods.

Note that while a zip member has been opened with openMember, you cannot use the add or addString methods, or open another member with openMember. No multitasking, bestie. ๐Ÿ™…โ€โ™€๏ธ

Also, if the enclosing zip object is closed whilst a filehandle is still open for a zip member, it will be closed automatically.

Returns a filehandle on success or undef on failure.

$z->close()

Returns 1 if the zip archive was closed successfully, or 0. Check the $SimpleZipError for a message. Bye bestie! ๐Ÿ‘‹


๐ŸŒˆ Options ๐ŸŒˆ

The majority of options are valid in both the constructor and in the methods that accept options. Any exceptions are noted in the text below.

Options specified in the constructor will be used as the defaults for all subsequent method calls.

For example, in the constructor below, the Method is set to ZIP_CM_STORE.

use Archive::Zip::SimpleZip qw($SimpleZipError) ;

my $z = Archive::Zip::SimpleZip->new('my.zip',
                                     Method => ZIP_CM_STORE)
    or die "Cannot create zip file: $SimpleZipError\n" ;

$z->add("file1");
$z->add("file2", Method => ZIP_CM_DEFLATE);
$z->add("file3");

$z->close();

The first call to add doesn't specify the Method option, so it uses the value from the constructor (ZIP_CM_STORE). The second call overrides the default set in the constructor to use ZIP_CM_DEFLATE. The third will revert to using the default, ZIP_CM_STORE. It's giving inheritance drama, but make it zip. ๐Ÿ’…

๐ŸŽ€ File Naming Options ๐ŸŽ€

A quick bit of zip file terminology โ€” A zip archive consists of one or more archive members, where each member has an associated filename, known as the archive member name.

The options listed in this section control how the archive member name (or filename) is stored the zip archive.

"Name => $string"

This option is used to explicitly set the archive member name in the zip archive to $string.

When used with the add method, this option will override any filename that was passed as a parameter.

The Name option is mandatory for the addString method.

This option is not valid in the constructor.

"CanonicalName => 0|1"

This option controls whether the archive member name is normalized into Unix format before being written to the zip archive.

It is very strongly recommended that you keep this option enabled unless you have a use cae where you really need to create a non-standard Zip archive. (Yes, "use cae" โ€” we're keeping the typo, it's part of the lore now. ๐Ÿ’€)

This is what APPNOTE.TXT has to say on what should be stored in the zip filename header field.

The name of the file, with optional relative path. The path stored should not contain a drive or device letter, or a leading slash. All slashes should be forward slashes '/' as opposed to backwards slashes '' for compatibility with Amiga and UNIX file systems etc.

This option defaults to true.

"FilterName => sub { ... }"

This option allow the archive member name to be modified before it is written to the zip archive.

This option takes a parameter that must be a reference to a sub. On entry to the sub the $_ variable will contain the name to be filtered. If no filename is available $_ will contain an empty string.

The value of $_ when the sub returns will be stored in the filename header field.

Note that if CanonicalName is enabled, a normalized filename will be passed to the sub.

If you use FilterName to modify the filename, it is your responsibility to keep the filename in Unix format.

See "Rename whilst adding" for an example of how the FilterName option can be used.

Taking all the options described above, the archive member name stored in a Zip archive is constructed as follows. ๐Ÿ‘€

Okay so where does the name that actually lands inside the zip even come from? ๐Ÿ’… Let's break it down, bestie.

The initial source for the archive member name that gets stored in the zip archive is the filename parameter supplied to the add method, or the value supplied with the Name option for the addString and openMember methods.

Next, if the add method is used, and the Name option is supplied, that will override the filename parameter. (Yes, Name wins. It's the main character here. ๐Ÿ‘‘)

If the CanonicalName option is enabled โ€” and bestie, it is enabled by default โ€” the archive member name gets normalized into Unix format. And if the filename was absolute, it gets changed into a relative filename. No more leading slashes, we're being polite now. โœจ

Finally, if the FilterName option is enabled, the filename gets passed to the sub supplied via the $_ variable. Whatever $_ holds on exit from that sub is what gets stored in the zip archive. You have full creative control, it's giving customization. ๐ŸŽ€

Here are some examples:

use Archive::Zip::SimpleZip qw($SimpleZipError) ;

my $z = Archive::Zip::SimpleZip->new('my.zip')
    or die "$SimpleZipError\n" ;

# store 'my/abc.txt' in the zip archive
$z->add('/my/abc.txt') ;

# store '/my/abc.txt' in the zip archive as an absolute path
$z->add('/my/abc.txt', CanonoicalName => 0) ;

# store '/some/file' as 'xyz' in the zip archive
$z->add('/some/file', Name => 'xyz') ;

# store 'file3.txt' in the zip archive by using a filter to remove the leading path
$z->add('/my/file3.txt', FilterName => sub { s#.*/## } ) ;

# no Name option, so store "" as the name in the zip archive
$z->addString('payload data') ;

# store 'xyz' in the zip archive
$z->addString('payload data', Name => 'xyz') ;

# store '/abc/def' in the zip archive as an absolute path
$z->addString('payload data', Name => '/abc/def', CanonoicalName => 0) ;

$z->close();

๐ŸŒˆ Overall Zip Archive Structure ๐ŸŒˆ

Minimal => 1|0

If you specify this, it disables the automatic creation of all the extra fields in the zip local and central headers โ€” with the exception of the ones that Zip64 absolutely needs, because those are non-negotiable. ๐Ÿ™…

In particular, these fields will not be created:

"UT" Extended Timestamp
"ux" ExtraExtra Type 3 (if running Unix)

This option is useful in a number of scenarios.

Firstly, it may be needed if you require the zip files created by Archive::Zip::SimpleZip to be read using a legacy version of unzip, or by an application that only supports a sub-set of the zip features. (Old software is out here with zero flexibility, we adapt. ๐Ÿ’€)

The other main use-case when Minimal is handy is when the data that Minimal suppresses is not needed, and so just adds unnecessary bloat to the zip file. The extra fields that Archive::Zip::SimpleZip adds by default all store information that assumes the entry in the zip file corresponds to a file that will be stored in a filesystem. This information is very useful when archiving files from a filesystem โ€” it means the unzipped files will more closely match their originals. But if the zip file isn't going to be unzipped to a filesystem, you can save a few bytes by enabling <Minimal>.

This parameter defaults to 0.

Stream => 0|1

This option controls whether the zip archive is created in streaming mode.

Heads up bestie: when outputting to a file or filehandle with streaming mode disabled (Stream is 0), the output file/handle must be seekable. No exceptions, no cap. ๐Ÿšจ

When outputting to '-' (STDOUT) the Stream option is automatically enabled for you. Slay, it handles itself.

The default is 0.

Zip64 => 0|1

ZIP64 is an extension to the Zip archive structure that allows:

  • Zip archives larger than 4Gig.
  • Zip archives with more that 64K members.

The module will automatically enable ZIP64 mode as needed when creating zip archive.

You can force creation of a Zip64 zip archive by enabling this option.

If you intend to manipulate the Zip64 zip archives created with this module using an external zip/unzip program/library, make sure that it supports Zip64. (Otherwise it's just gonna stare at your beautiful archive like ??? ๐Ÿ˜ญ)

The default is 0.


โœจ Other Options โœจ

AutoFlush => 0|1

When true, this option enables flushing of the underlying filehandle after each write/print operation.

If SimpleZip is writing to a buffer, this option is ignored.

Comment => $comment

This option allows the creation of a comment that is associated with the member added to the zip archive with the add and addString methods.

This option is not valid in the constructor. Don't try it, it will not be the vibe.

By default, no comment field is written to the zip archive.

Encode => "encoding"

The Encode option allows you to set the character encoding of the data before it is compressed and written to the zip file. The option is only valid with the add or addString methods. It will be ignored if you use it with the add option.

Under the hood this option relies on the Encode module to carry do the hard work. In particular it uses the Encode::find_encoding to check that the encoding you have requested exists.

use Archive::Zip::SimpleZip qw($SimpleZipError) ;

my $z = Archive::Zip::SimpleZip->new('my.zip')
    or die "$SimpleZipError\n" ;

$z->addString("payload data", Encode => "utf8") ;

Method => $method

Controls which compression method is used. At present the compression methods supported are: Store (no compression at all), Deflate, Bzip2, Zstd, Xz and Lzma.

The symbols ZIP_CM_STORE, ZIP_CM_DEFLATE, ZIP_CM_BZIP2, ZIP_CM_ZSTD, ZIP_CM_XZ and ZIP_CM_LZMA are used to select the compression method.

These constants are not imported by default by this module. So if you want them, go get them:

use Archive::Zip::SimpleZip qw(:zip_method);
use Archive::Zip::SimpleZip qw(:constants);
use Archive::Zip::SimpleZip qw(:all);

Note that to create Bzip2 content, the module IO::Compress::Bzip2 must be installed. A fatal error will be thrown if you attempt to create Bzip2 content when IO::Compress::Bzip2 is not available. ๐Ÿ’€

Note that to create Lzma content, the module IO::Compress::Lzma must be installed. A fatal error will be thrown if you attempt to create Lzma content when IO::Compress::Lzma is not available.

Note that to create Xz content, the module IO::Compress::Xz must be installed. A fatal error will be thrown if you attempt to create Xz content when IO::Compress::Xz is not available.

Note that to create Zstd content, the module IO::Compress::Zstd must be installed. A fatal error will be thrown if you attempt to create Zstd content when IO::Compress::Zstd is not available.

The default method is ZIP_CM_DEFLATE for files and ZIP_CM_STORE for directories and symbolic links.

Controls what Archive::Zip::SimpleZip does with a symbolic link (assuming your operating system supports .

When true, it stores the link itself. When false, it stores the contents of the file the link refers to.

If your platform does not support symbolic links this option is ignored.

Default is 0.

TextFlag => 0|1

This parameter controls the setting of a flag in the zip central header. It is used to signal that the data stored in the zip archive is probably text.

The default is 0.

ZipComment => $comment

This option allows the creation of a comment field for the entire zip archive.

This option is only valid in the constructor. Constructor only, periodt. ๐Ÿ’…

By default, no comment field is written to the zip archive.


๐Ÿ”ฅ Deflate Compression Options ๐Ÿ”ฅ

These options are only valid if the Method is ZIP_CM_DEFLATE. They are ignored otherwise.

Level => value

Defines the compression level used by zlib. The value should either be a number between 0 and 9 (0 means no compression and 9 is maximum compression), or one of the symbolic constants defined below.

Z_NO_COMPRESSION
Z_BEST_SPEED
Z_BEST_COMPRESSION
Z_DEFAULT_COMPRESSION

The default is Z_DEFAULT_COMPRESSION.

Strategy => value

Defines the strategy used to tune the compression. Use one of the symbolic constants defined below.

Z_FILTERED
Z_HUFFMAN_ONLY
Z_RLE
Z_FIXED
Z_DEFAULT_STRATEGY

The default is Z_DEFAULT_STRATEGY.


๐ŸŒธ Bzip2 Compression Options ๐ŸŒธ

These options are only valid if the Method is ZIP_CM_BZIP2. They are ignored otherwise.

BlockSize100K => number

Specify the number of 100K blocks bzip2 uses during compression.

Valid values are from 1 to 9, where 9 is best compression.

The default is 1.

WorkFactor => number

Specifies how much effort bzip2 should take before resorting to a slower fallback compression algorithm.

Valid values range from 0 to 250, where 0 means use the default value 30.

The default is 0.


๐Ÿฆ‹ Lzma & XZ Compression Options ๐Ÿฆ‹

These options are only valid if the Method is ZIP_CM_LZMA or ZIP_CM_LZMA. They are ignored otherwise.

Preset => number

Used to choose the LZMA compression preset.

Valid values are 0-9 and LZMA_PRESET_DEFAULT.

0 is the fastest compression with the lowest memory usage and the lowest compression.

9 is the slowest compession with the highest memory usage but with the best compression.

Defaults to LZMA_PRESET_DEFAULT (6).

Extreme => 0|1

Makes LZMA compression a lot slower, but a small compression gain.

Defaults to 0.


๐Ÿงš Zstd Compression Options ๐Ÿงš

These options are only valid if the Method is ZIP_CM_ZSTD. They are ignored otherwise.

Level =>

Defines the compression level used.

Default value is 3.


โญ Summary of Default Behaviour โญ

By default Archive::Zip::SimpleZip will do the following:

  • Use Deflate Compression for all standard files.
  • Create a non-streamed Zip archive.
  • Follow Symbolic Links.
  • Canonicalise the filename before adding it to the zip archive.
  • Only create a ZIP64 Zip archive if any of the input files is greater than 4 Gig or there are more than 64K members in the zip archive.
  • Fill out the following zip extended attributes:
"UT" Extended Timestamp
"ux" ExtraExtra Type 3 (if running Unix)

You can change the behaviour of most of the features mentioned above. Your zip, your rules. ๐Ÿซถ

โœจ EXAMPLES โœจ

okay bestie, this is the part where we get our hands dirty with actual code. no cap. ๐Ÿ’…

๐ŸŒธ A Simple example ๐ŸŒธ

Say you wanna add all the "C" files in the current directory to the zip archive "my.zip". Here's the whole vibe:

use Archive::Zip::SimpleZip qw($SimpleZipError) ;

my $z = Archive::Zip::SimpleZip->new('my.zip')
    or die "$SimpleZipError\n" ;

for ( <*.c> )
{
    $z->add($_)
        or die "Cannot add '$_' to zip file: $SimpleZipError\n" ;
}

$z->close();

๐Ÿง  Creating an in-memory Zip archive ๐Ÿง 

All you gotta do if you want the zip archive created in-memory is pass a string reference to the constructor. The example below stores the zip archive in the variable $zipData. No filesystem drama. โœจ

use Archive::Zip::SimpleZip qw($SimpleZipError) ;

my $zipData ;
my $z = Archive::Zip::SimpleZip->new(\$zipData)
    or die "$SimpleZipError\n" ;

$z->add('part1.txt');
$z->close();

And here's a lil' refinement of the in-memory story. Besides writing the zip archive into memory, this example uses addString to create the member "part2.txt" without reading anything from the filesystem. Iconic. ๐Ÿฆ‹

use Archive::Zip::SimpleZip qw($SimpleZipError) ;

my $zipData ;
my $z = Archive::Zip::SimpleZip->(\$zipData)
    or die "$SimpleZipError\n" ;

$z->addString('some text', Name => 'part2.txt');
$z->close();

๐ŸŽ€ Rename whilst adding ๐ŸŽ€

This example shows how the FilterName option can be used to remove the path from the filename before it gets written to the zip archive, "my.zip". Slay.

use Archive::Zip::SimpleZip qw($SimpleZipError) ;

my $z = Archive::Zip::SimpleZip->new('my.zip')
    or die "$SimpleZipError\n" ;

for ( </some/path/*.c> )
{
    $z->add($_, FilterName => sub { s[^.*/][] }  )
        or die "Cannot add '$_' to zip file: $SimpleZipError\n" ;
}

$z->close();

๐ŸŒˆ Adding a directory tree to a Zip archive ๐ŸŒˆ

If you need to add all (or part) of a directory tree into a Zip archive, you can use the standard Perl module File::Find with this module. Tag team. ๐Ÿค

This code snippet assumes you want the non-directory files in the directory tree "myDir" added to the zip archive "found.zip". It also assumes you don't want the added files to include any part of the "myDir" relative path.

use strict;
use warnings;

use Archive::Zip::SimpleZip;
use File::Find;

my $filename = "found.zip";
my $dir = "myDir";
my $z = Archive::Zip::SimpleZip->new($filename)
    or die "Cannot open file $filename\n";

find( sub { $z->add($_) if ! -d $_ }, $dir);

$z->close();

If you do want to include relative paths, pass the $File::Find::name variable with the "Name" option, like this:

find( sub
      {
          $z->add($_, Name => $File::Find::name)
               if ! -d $_
      },
      $dir);

๐Ÿ“ Using addFileHandle ๐Ÿ“

Say you've got a bunch of old-style ".Z" compressed files and you wanna uncompress them and put them into a zip file. The script below, Z2zip.pl, does exactly that. No cap.

use strict;
use warnings;

use Archive::Zip::SimpleZip qw($SimpleZipError);

die "Usage: Z2zip.pl zipfilename file1.Z file2.Z...\n"
    unless @ARGV >= 2 ;

my $zipFile = shift ;
my $zip = Archive::Zip::SimpleZip->new($zipFile)
            or die "Cannot create zip file '$zipFile': $SimpleZipError";

for my $Zfile (@ARGV)
{
    my $cleanName = $Zfile ;
    $cleanName =~ s/\.Z$//;

    print "Adding $cleanName\n" ;

    open my $z, "uncompress -c $Zfile |" ;

    $zip->addFileHandle($z, Name => $cleanName)
        or die "Cannot addFileHandle '$cleanName': $SimpleZipError\n" ;
}

๐Ÿงš Another filehandle example - Working with Net::FTP ๐Ÿงš

Say you wanna read all the json files from ftp://ftp.perl.org/pub/CPAN/ using Net::FTP and write them directly to a zip archive without storing them in the filesystem first. Big brain energy. ๐Ÿง 

Here are a couple of ways to do that. The first uses the openMember method with the Net::FTP::get method, like so:

use strict;
use warnings;

use Net::FTP;
use Archive::Zip::SimpleZip qw($SimpleZipError);

my $zipFile = 'json.zip';
my $host = 'ftp.perl.org';
my $path = '/pub/CPAN';

my $zip = Archive::Zip::SimpleZip->new($zipFile)
        or die "Cannot create zip file '$zipFile': $SimpleZipError";

my $ftp = Net::FTP->new($host)
    or die "Cannot connect to $host: $@";

$ftp->login('anonymous','-anonymous@')
    or die "Cannot login ", $ftp->message;

$ftp->cwd($path)
    or die "Cannot change working directory ", $ftp->message;

my @files = $ftp->ls()
    or die "Cannot ls", $ftp->message;

for my $file ( grep { /json$/ } @files)
{
    print " Adding $file\n" ;

    my $zipMember = $zip->openMember(Name => $file)
        or die "Cannot openMember file '$file': $SimpleZipError\n" ;

    $ftp->get($file, $zipMember)
        or die "Cannot get", $ftp->message;
}

Alternatively, Net::FTP allows a read filehandle to be opened for a file to be transferred using the retr method. This filehandle can be dropped into a zip archive using addFileHandle. The code below rewrites the for loop from the previous version to show how it's done.

for my $file ( grep { /json$/ } @files)
{
    print " Adding $file\n" ;

    my $fh = $ftp->retr($file)
        or die "Cannot get", $ftp->message;

    $zip->addFileHandle($fh, Name => $file)
        or die "Cannot addFileHandle file '$file': $SimpleZipError\n" ;

    $fh->close()
        or die 'Cannot close', $ftp->message;
}

One thing to be aware of with Net::FTP::retr: not all FTP servers support it. See Net::FTP for details on how to find out what features an FTP server implements. ๐Ÿ‘€


๐Ÿ’œ Creating a Zip file from STDIN ๐Ÿ’œ

The script below, zipstdin, shows how to create a zip file using data read from STDIN.

use strict;
use warnings;

use Archive::Zip::SimpleZip qw($SimpleZipError);

my $zipFile = 'stdin.zip';

my $zip = Archive::Zip::SimpleZip->new($zipFile)
        or die "Cannot create zip file '$zipFile': $SimpleZipError";
$zip->adFilehandle(STDIN, Name => "data.txt") ;

Or this, to do the whole thing from the command line:

echo abc | perl -MArchive::Zip::SimpleZip -e 'Archive::Zip::SimpleZip->new('stdin.zip')->addFileHandle(STDIN, Name => 'data.txt')'

๐Ÿ’… IMPORTING ๐Ÿ’…

A bunch of symbolic constants are required by some methods in Archive::Zip::SimpleZip. None are imported by default. So you gotta ask nicely. ๐Ÿ’…

  • :all โ€” Imports zip, $SimpleZipError and all symbolic constants that can be used by IArchive::Zip::SimpleZip. Same as doing this:
use Archive::Zip::SimpleZip qw(zip $SimpleZipError :constants) ;
  • :constants โ€” Import all symbolic constants. Same as doing this:
use Archive::Zip::SimpleZip qw(:flush :level :strategy :zip_method) ;
  • :flush โ€” These symbolic constants are used by the flush method.
Z_NO_FLUSH
Z_PARTIAL_FLUSH
Z_SYNC_FLUSH
Z_FULL_FLUSH
Z_FINISH
Z_BLOCK
  • :level โ€” These symbolic constants are used by the Level option in the constructor.
Z_NO_COMPRESSION
Z_BEST_SPEED
Z_BEST_COMPRESSION
Z_DEFAULT_COMPRESSION
  • :strategy โ€” These symbolic constants are used by the Strategy option in the constructor.
Z_FILTERED
Z_HUFFMAN_ONLY
Z_RLE
Z_FIXED
Z_DEFAULT_STRATEGY
  • :zip_method โ€” These symbolic constants are used by the Method option in the constructor.
ZIP_CM_STORE
ZIP_CM_DEFLATE
ZIP_CM_BZIP2

๐Ÿ’– FAQ ๐Ÿ’–

Can SimpleZip update an existing Zip file?

Nope, bestie. You can only create a zip file from scratch. No editing existing ones. Periodt. ๐Ÿ’…

Can I write a Zip Archive to STDOUT?

Yes. Writing zip files to filehandles that are not seekable (so that includes both STDOUT and sockets) is supported by this module. You just have to set the Stream option when you call the constructor.

use Archive::Zip::SimpleZip qw($SimpleZipError) ;

my $zipData ;
my $z = Archive::Zip::SimpleZip->new('-'),
                    Stream => 1
    or die "$SimpleZipError\n" ;

$z->add("file1.txt");
$z->close();

See "What is a Streamed Zip file?" for a discussion on the Stream option.

Can I write a Zip Archive directly to a socket?

See previous question. Same energy. ๐Ÿ’…

What is a Streamed Zip file?

Streaming mode allows you to write a zip file in situations where you cannot seek backwards/forwards. The classic examples are when you're working with sockets or need to write the zip file to STDOUT.

By default Archive::Zip::SimpleZip does not use streaming mode when writing to a zip file (you need to set the Stream option to 1 to enable it).

If you plan to create a streamed Zip file, be aware that it will be slightly larger than the non-streamed equivalent. If the files you archive are 32-bit the overhead will be an extra 16 bytes per file written to the zip archive. For 64-bit it is 24 bytes per file. Math is math. ๐Ÿงฎ


๐Ÿซถ SUPPORT ๐Ÿซถ

Got feedback, questions, or bug reports? Send them to https://github.com/pmqs/Archive-Zip-SimpleZip/issues (preferred) or https://rt.cpan.org/Public/Dist/Display.html?Name=Archive-Zip-SimpleZip. The maintainer will love you for it. ๐Ÿซถ


๐Ÿ‘€ SEE ALSO ๐Ÿ‘€

  • Archive::Zip::SimpleUnzip
  • IO::Compress::Zip
  • Archive::Zip
  • IO::Uncompress::UnZip

๐Ÿ‘‘ AUTHOR ๐Ÿ‘‘

This module was written by Paul Marquess, pmqs@cpan.org. Absolute legend. ๐Ÿ‘‘


๐Ÿ“œ MODIFICATION HISTORY ๐Ÿ“œ

See the Changes file for the full story. ๐Ÿ“œ


Copyright (c) 2012-2024 Paul Marquess. All rights reserved. ๐Ÿ’–

This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. Periodt.


okay bestie, that's the whole page! this was perl v5.42.0, dated 2025-07-25, and the page is Archive...impleZip(3). now go forth and zip something iconic ๐Ÿ’…โœจ

๐Ÿ“ฆ where this page comes from