in reply to Reading data from ZIP data in a File::Temp filehandle problem

In your second example, you never rewind $tmp to its start position. Maybe Archive::Zip wants that?

Replies are listed 'Best First'.
Re^2: Reading data from ZIP data in a File::Temp filehandle problem
by drewhead (Beadle) on Sep 14, 2011 at 19:28 UTC
    Thanks for the response. I added a rewind thusly:
    ###################################################################### # This doesn't { my $ua = LWP::UserAgent->new; $ua->timeout(10); $ua->env_proxy; my $response = $ua->get($url); my $tmp = File::Temp->new(); if ($response->is_success) { binmode($tmp); print $tmp $response->decoded_content; print "Wrote ".$tmp->filename()."\n"; $tmp->seek(0,0); # Added rewind } else { die "error ".$response->status_line; } unless (-B $tmp) { die "Did not get a filehandle\n"; } my $zip = Archive::Zip->new(); my $zip_err = $zip->readFromFileHandle( $tmp ); unless ($zip_err == AZ_OK ) { die "Archive::Zip read error on filehandle: $zip_err\n"; } foreach my $member ($zip->members()) { my $fileName = $member->fileName(); print "fileName = $fileName\n"; my $content = $member->contents(); print "contents $fileName = ".Dumper($content); } }
    which didn't appear to affect the issue.

      It seems that ->readFromFileHandle really wants the filename. The following works for me:

      use strict; use LWP::UserAgent; use Archive::Zip; use Archive::Zip qw( :ERROR_CODES :CONSTANTS ); use Data::Dumper; my $url = 'http://keep.drewhead.org/test.zip'; my $file = '../test.zip'; # a local copy of $url # This doesn't { my $ua = LWP::UserAgent->new; $ua->timeout(10); $ua->env_proxy; my $response = $ua->get($url); warn length($response->decoded_content); my $tmp; if ($response->is_success) { $tmp = File::Temp->new(); binmode $tmp; print {$tmp} $response->decoded_content; print "Wrote ".$tmp->filename()."\n"; } else { die "error ".$response->status_line; } #unless (-B $tmp) { die "Did not get a filehandle\n"; } my $zip = Archive::Zip->new(); my $zip_err = $zip->readFromFileHandle( $tmp, $tmp->filename ); unless ($zip_err == AZ_OK ) { die "Archive::Zip read error on filehandle: $zip_err\n"; } foreach my $member ($zip->members()) { my $fileName = $member->fileName(); print "fileName = $fileName\n"; my $content = $member->contents(); print "contents $fileName = ".Dumper($content); } }

      I added the binmode call before writing the tempfile, and I pass the name of the tempfile down to ->readFromFileHandle().

        That seems to work when implemented in my larger application. It does seem odd to me that the file is required for a method called readFromFileHandle.

        In context of my app the code that is doing the Zip actions is separate from the code that is doing the URL retrieval and temp storage. So I was hoping to be able to just pass the filehandle reference around. Passing both the filehandle reference and a reference to the file itself is doable, but leaves me unsettled. :/

        Thanks again for your help.