Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses
 
PerlMonks  

Reading CGI.pm file upload spools with Archive::Zip

by OverlordQ (Hermit)
on Sep 01, 2004 at 19:32 UTC ( [id://387666] : perlquestion . print w/replies, xml ) Need Help??

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

Greetings monks! First, I'll start off with the code, so you can tell me if I'm even going in the right direction. Then I'll tell you my problem.
#!/usr/bin/perl -w use strict; use CGI; use Archive::Zip; ##Initialize CGI my $cgi = new CGI; print $cgi->header(); ##Ohnoes start over unless( $cgi->param('step') ) { starthtml(); print <<HTML; <font face="Verdana, Arial, Helvetica, sans-serif">Please enter th +e number of files you need to upload: HTML ##FormStuff print $cgi->start_form; print $cgi->textfield('nfiles'); print $cgi->hidden('step','2'); print $cgi->submit; print $cgi->end_form; ##Finish off Teh HTML print <<HTML; </p></div> </body> </html> HTML } if ( $cgi->param('step') == '2' ) { ##Clear the step num $cgi->delete('step'); starthtml(); ##Start Form and loop through to create number of upload fields we + need print $cgi->start_form; for(my $i = 1; $i <= $cgi->param('nfiles');$i++) { print $cgi->filefield(-name=>"file$i"),"<br />\n"; } ##Next step, also send number of files again print $cgi->hidden('step','3'); print $cgi->hidden('nfiles',$cgi->param('nfiles')); print $cgi->submit(); print $cgi->end_form(); } elsif ( $cgi->param('step') == '3' ) { ##Here is teh problem## my @files; for (my $i = 1; $i <= $cgi->param('nfiles'); $i++) { my $filename = $cgi->param("file$i"); my $upload_filehandle = $cgi->upload("file$i"); ## Probably no +t the best way to do that but ohwell ### ### Archive::Zip Processing here ### } sub starthtml { print <<START; <html> <head> <title>Update Tool</title> </head> <body bgcolor="#006633"> <div align="center"> <p><font size="+2" face="Verdana, Arial, Helvetica, sans-serif +">Update Tool</font><br /> <br /> <br /> START }
I read over the CGI.pm docs and calling the upload() method will return the filehandle to the temporary file that CGI.pm created. But looking over Archive::Zip, it looks as if it wants the name of the zip in the new() constructor. Are there any CGI.pm calls I'm missing that I can get the name of the file? Or will I have to write to disk ala:
open (OUTFILE,">>/tmp/file"); binmode(OUTFILE); while ($bytesread=read($filename,$buffer,1024)) { print OUTFILE $buffer; }
then read the file with Archive::Zip, process what needs done, then unlink?

Replies are listed 'Best First'.
Re: Reading CGI.pm file upload spools with Archive::Zip
by ikegami (Patriarch) on Sep 01, 2004 at 19:43 UTC

    $zip = Archive::Zip->new(...);
    is the same as
    $zip = Archive::Zip->new();
    my $status = $zip->read(...);
    $zip = undef unless ($status == AZ_OK);
    so use
    $zip = Archive::Zip->new();
    my $status = $zip->readFromFileHandle($upload_filehandle);
    $zip = undef unless ($status == AZ_OK);

    Untested.

    Update: You know what, it looks like read() and (therefore) new() accept a filehandle as an alternative to a file name. So, $zip = Archive::Zip->new($upload_filehandle); should work fine.

      Hmmm I tried your first code, but i got this:
      print "On file: $i\n<br>"; my $filename = $cgi->param("file1") or print "Cannot do that: $!\n"; print "Uploading . . ."; my $upload_filehandle = $cgi->upload("file$i") or print "cant upload: +$!\n"; print "done<br>\n"; print "Making zip . . ."; my $zip = Archive::Zip->new() or print "Canot make zippah: $!\n"; print "done<br>\n"; print "Reading Zip . . . "; my $status = $zip->readFromFilehandle($upload_filehandle); print "done<br>\n"; print "Mah Statuhs: $status\n"; $zip = undef unless ($status eq 'AZ_OK'); if(defined($zip)) { print $zip->members(); } else { print "Ooops something happened: $!\n"; }
      But this is what I get for output:
      Mungeing!
      On file: 1
      Uploading . . .done
      Making zip . . .done
      Reading Zip . . .
      Dunno what's up there :-(
        I really do not have a explination, and if someone has one I would like to know. You have to make a reference of the dereferenced file handler object. In your case you read line should look like this.

        my $status = $zip->readFromFilehandle(\$$upload_filehandle);

        Here a segement of code that I used to get this working...

        my $fh = $c->upload('zip');
        my $zip = Archive::Zip->new();
        $zip->read(\$$fh);

        my @members = $zip->members();

        foreach my $member (@members){
        my $filename = $member->fileName();
        print "$filename\n";
        }