1#!/usr/bin/perl 2 3# Streaming zip 4 5use strict; 6use warnings; 7 8use IO::Compress::Zip qw(zip 9 ZIP_CM_STORE 10 ZIP_CM_DEFLATE 11 ZIP_CM_BZIP2 ) ; 12 13use Getopt::Long; 14 15my $VERSION = '1.00'; 16 17my $compression_method = ZIP_CM_DEFLATE; 18my $stream = 0; 19my $zipfile = '-'; 20my $memberName = '-' ; 21my $zip64 = 0 ; 22my $level ; 23 24GetOptions("zip64" => \$zip64, 25 "method=s" => \&lookupMethod, 26 "0" => sub { $level = 0 }, 27 "1" => sub { $level = 1 }, 28 "2" => sub { $level = 2 }, 29 "3" => sub { $level = 3 }, 30 "4" => sub { $level = 4 }, 31 "5" => sub { $level = 5 }, 32 "6" => sub { $level = 6 }, 33 "7" => sub { $level = 7 }, 34 "8" => sub { $level = 8 }, 35 "9" => sub { $level = 9 }, 36 "stream" => \$stream, 37 "zipfile=s" => \$zipfile, 38 "member-name=s" => \$memberName, 39 'version' => sub { print "$VERSION\n"; exit 0 }, 40 'help' => \&Usage, 41 ) 42 or Usage(); 43 44Usage() 45 if @ARGV; 46 47my @extraOpts = (); 48 49if ($compression_method == ZIP_CM_DEFLATE && defined $level) 50{ 51 push @extraOpts, (Level => $level) 52} 53 54# force streaming zip file when writing to stdout. 55$stream = 1 56 if $zipfile eq '-'; 57 58zip '-' => $zipfile, 59 Name => $memberName, 60 Zip64 => $zip64, 61 Method => $compression_method, 62 Stream => $stream, 63 @extraOpts 64 or die "Error creating zip file '$zipfile': $\n" ; 65 66exit 0; 67 68sub lookupMethod 69{ 70 my $name = shift; 71 my $value = shift ; 72 73 my %valid = ( store => ZIP_CM_STORE, 74 deflate => ZIP_CM_DEFLATE, 75 bzip2 => ZIP_CM_BZIP2, 76 lzma => 14, 77 xz => 95, 78 zstd => 93, 79 ); 80 81 my $method = $valid{ lc $value }; 82 83 Usage("Unknown method '$value'") 84 if ! defined $method; 85 86 installModule("Lzma") 87 if $method == 14 ; 88 89 installModule("Xz") 90 if $method == 95 ; 91 92 installModule("Zstd") 93 if $method == 93; 94 95 $compression_method = $method; 96} 97 98sub installModule 99{ 100 my $name = shift ; 101 102 eval " use IO::Compress::$name; use IO::Compress::Adapter::$name ; " ; 103 die "Method '$name' needs IO::Compress::$name\n" 104 if $@; 105} 106 107sub Usage 108{ 109 print <<EOM; 110Usage: 111 producer | streamzip [OPTIONS] | consumer 112 producer | streamzip [OPTIONS] -zipfile output.zip 113 114Stream data from stdin, compress into a Zip container, and either stream to stdout, or 115write to a named file. 116 117OPTIONS 118 119 -zipfile=F Write zip container to the filename 'F' 120 Outputs to stdout if zipfile not specified. 121 -member-name=M Set member name to 'M' [Default '-'] 122 -0 ... -9 Set compression level for Deflate 123 [Default: 6] 124 -zip64 Create a Zip64-compliant zip file [Default: No] 125 Enable Zip64 if input is greater than 4Gig. 126 -stream Force a streamed zip file when 'zipfile' option is also enabled. 127 Only applies when 'zipfile' option is used. [Default: No] 128 Stream is always enabled when writing to stdout. 129 -method=M Compress using method 'M'. 130 Valid methods are 131 store Store without compression 132 deflate Use Deflate compression [Deflault] 133 bzip2 Use Bzip2 compression 134 lzma Use LZMA compression [needs IO::Compress::Lzma] 135 xz Use LZMA compression [needs IO::Compress::Xz] 136 zstd Use LZMA compression [needs IO::Compress::Zstd] 137 -version Display version number [$VERSION] 138 139Copyright (c) 2019-2024 Paul Marquess. All rights reserved. 140 141This program is free software; you can redistribute it and/or 142modify it under the same terms as Perl itself. 143 144EOM 145 exit; 146} 147 148 149__END__ 150=head1 NAME 151 152streamzip - create a zip file from stdin 153 154=head1 SYNOPSIS 155 156 producer | streamzip [opts] | consumer 157 producer | streamzip [opts] -zipfile=output.zip 158 159=head1 DESCRIPTION 160 161This program will read data from C<stdin>, compress it into a zip container 162and, by default, write a I<streamed> zip file to C<stdout>. No temporary 163files are created. 164 165The zip container written to C<stdout> is, by necessity, written in 166streaming format. Most programs that read Zip files can cope with a 167streamed zip file, but if interoperability is important, and your workflow 168allows you to write the zip file directly to disk you can create a 169non-streamed zip file using the C<zipfile> option. 170 171=head2 OPTIONS 172 173=over 5 174 175=item -zip64 176 177Create a Zip64-compliant zip container. Use this option if the input is 178greater than 4Gig. 179 180Default is disabled. 181 182=item -zipfile=F 183 184Write zip container to the filename C<F>. 185 186Use the C<Stream> option to force the creation of a streamed zip file. 187 188=item -member-name=M 189 190This option is used to name the "file" in the zip container. 191 192Default is '-'. 193 194=item -stream 195 196Ignored when writing to C<stdout>. 197 198If the C<zipfile> option is specified, including this option will trigger 199the creation of a streamed zip file. 200 201Default: Always enabled when writing to C<stdout>, otherwise disabled. 202 203=item -method=M 204 205Compress using method C<M>. 206 207Valid method names are 208 209 * store Store without compression 210 * deflate Use Deflate compression [Deflault] 211 * bzip2 Use Bzip2 compression 212 * lzma Use LZMA compression 213 * xz Use xz compression 214 * zstd Use Zstandard compression 215 216Note that Lzma compress needs C<IO::Compress::Lzma> to be installed. 217 218Note that Zstd compress needs C<IO::Compress::Zstd> to be installed. 219 220Default is C<deflate>. 221 222=item -0, -1, -2, -3, -4, -5, -6, -7, -8, -9 223 224Sets the compression level for C<deflate>. Ignored for all other compression methods. 225 226C<-0> means no compression and C<-9> for maximum compression. 227 228Default is 6 229 230=item -version 231 232Display version number 233 234=item -help 235 236Display help 237 238=back 239 240=head2 Examples 241 242Create a zip file bt reading daa from stdin 243 244 $ echo Lorem ipsum dolor sit | perl ./bin/streamzip >abcd.zip 245 246Check the contents of C<abcd,zip> with the standard C<unzip> utility 247 248 Archive: abcd.zip 249 Length Date Time Name 250 --------- ---------- ----- ---- 251 22 2021-01-08 19:45 - 252 --------- ------- 253 22 1 file 254 255Notice how the C<Name> is set to C<->. 256That is the default for a few zip utilities whwre the member name is not given. 257 258If you want to explicitly name the file, use the C<-member-name> option as follows 259 260 $ echo Lorem ipsum dolor sit | perl ./bin/streamzip -member-name latin >abcd.zip 261 262 $ unzip -l abcd.zip 263 Archive: abcd.zip 264 Length Date Time Name 265 --------- ---------- ----- ---- 266 22 2021-01-08 19:47 latin 267 --------- ------- 268 22 1 file 269 270 271=head2 When to write a Streamed Zip File 272 273A Streamed Zip File is useful in situations where you cannot seek 274backwards/forwards in the file. 275 276A good examples is when you are serving dynamic content from a Web Server 277straight into a socket without needing to create a temporary zip file in 278the filesystsm. 279 280Similarly if your workfow uses a Linux pipelined commands. 281 282=head1 SUPPORT 283 284General feedback/questions/bug reports should be sent to 285L<https://github.com/pmqs/IO-Compress/issues> (preferred) or 286L<https://rt.cpan.org/Public/Dist/Display.html?Name=IO-Compress>. 287 288 289=head1 AUTHOR 290 291Paul Marquess F<pmqs@cpan.org>. 292 293=head1 COPYRIGHT 294 295Copyright (c) 2019-2024 Paul Marquess. All rights reserved. 296 297This program is free software; you can redistribute it and/or modify it 298under the same terms as Perl itself. 299