Bivio::IO::Zip
# Copyright (c) 2008 bivio Software, Inc. All Rights Reserved. # $Id$ package Bivio::IO::Zip; use strict; use Bivio::Base 'Bivio::UNIVERSAL'; use Archive::Zip (); use IO::File (); b_use('IO.Trace'); our($_TRACE); my($_IDI) = __PACKAGE__->instance_data_index; my($_F) = b_use('IO.File'); sub add_file { # Adds the named file to the archive. This is the preferable way to add a # file because it is not brought into memory. my($self, $path, $name) = @_; my($fields) = $self->[$_IDI]; _trace($path, ' ', $name) if $_TRACE; b_die('file not found for zip: ', $path) unless -r $path; $fields->{zip}->addFile($path, $name); return $self; } sub add_string { # Adds the in-memory file contents to the archive. my($self, $contents, $name) = @_; my($fields) = $self->[$_IDI]; _trace($name) if $_TRACE; $fields->{zip}->addString($contents, $name) ->desiredCompressionMethod(Archive::Zip::COMPRESSION_DEFLATED); return $self; } sub get_member_count { my($self) = @_; my($fields) = $self->[$_IDI]; return $fields->{zip}->numberOfMembers; } sub iterate_members { # Iterates each member of the zip file, calling # handler->(member, contents). # Stops iteratation if handler returns false. my($self, $handler) = @_; my($fields) = $self->[$_IDI]; foreach my $member ($fields->{zip}->members) { last unless $handler->($member->fileName, \($fields->{zip}->contents($member))); } return $self; } sub new { my($proto) = shift; my($self) = $proto->SUPER::new(@_); $self->[$_IDI] = { zip => Archive::Zip->new, }; Archive::Zip::setErrorHandler(sub {b_die(shift)}); return $self; } sub read_zip_from_string { # Loads the instance from an in-memory value. my($self, $zip_contents) = @_; my($fields) = $self->[$_IDI]; my($file) = $_F->temp_file($self->req); $_F->write($file, $zip_contents); $fields->{zip} = Archive::Zip->new; b_die('failed to read zip from string') unless $fields->{zip}->read($file) == Archive::Zip::AZ_OK(); return $self; } sub send_zip_to_client { # Saves the zip file to disk, sets the file handle for the request output. my($self, $req) = @_; my($file_name) = $_F->temp_file($req); $self->write_to_file($file_name); $req->get('reply')->set_output(IO::File->new($file_name, 'r') || b_die('file open failed: ', $file_name)) ->set_output_type('application/zip'); return $self; } sub write_to_file { my($self, $filename) = @_; my($fields) = $self->[$_IDI]; b_die('failed to write zip file') unless $fields->{zip}->writeToFileNamed($filename) == Archive::Zip::AZ_OK(); return $self; } 1;