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

Hey monks,

I'm trying to use Archive::Zip to compress some text files for clients to download, but they appear to be corrupted. I get an error message, and only the first file in the .zip is extracted (regardless of which file that is).

I can see all the files when I look at the compressed file contents.

I am using Centos 5.2 x86_64 with perl 5.8.8 and Archive::Zip 1.30. Here is the error message I get:
warning [/home/student1/Desktop/compounds1310483480.zip]: 104 extra b +ytes at beginning or within zipfile (attempting to process anyway) file #1: bad zipfile offset (local header sig): 104 (attempting to re-compensate) bad CRC 50b35a73 (should be 00000000) file #2: bad zipfile offset (local header sig): 405 (attempting to re-compensate) file #2: bad zipfile offset (local header sig): 405 file #3: bad zipfile offset (local header sig): 1020 file #4: bad zipfile offset (local header sig): 1552

The errors I get when attempting to extract the files in Windows/OSX are 'corrupt/invalid'.

Here is the code I use to create the zip file:

foreach my $memberName (@MOL2_files) { if (-d $memberName ) { print $log "Adding $memberName\n"; warn (print $log "Error adding directory $memberName\n") if $zip->addTree( $memberName, $memberName) != AZ_OK; } else { print $log "Adding $memberName\n"; $zip->addFile( "/www/mol2/$memberName", "compounds".$time."/". +$memberName ) or warn (print $log "Error adding file $memberName\n"); } } open my $fh, ">>", $fullpath or die $!; print $log "Write Error.\n" if $zip->writeToFileNamed( $fh ) != AZ_OK;

Has anyone seen this problem before and know how to fix it? Or does anyone know of a different module I can use to perform the same function?

Thanks, Tom

Replies are listed 'Best First'.
Re: Archive::Zip - zip files are corrupted or invalid
by Corion (Patriarch) on Jul 12, 2011 at 16:04 UTC

    When reading or writing binary files, always use binmode immediately after opening the filehandle.

    ... open my $fh, ">>", $fullpath or die $!; binmode $fh;

    Also, when transferring a binary file, use "binary" mode in ftp.

      Hi, thanks for the quick reply. I've made the change:
      open my $fh, ">>", $fullpath or die $!; binmode $fh; print $log "Writer error.\n" if $zip->writeToFileNamed( $fh ) != AZ_OK +; close $fh;
      But I still receive the same error on the file that is directly created by my script, not the one sent through ftp, so the binary mode in ftp wouldn't be the problem.
        $zip->writeToFileNamed( $fh )

        is likely wrong, at least when looking at Archive::Zip. You either want

        $zip->writeToFileHandle( $fh )

        or

        $zip->writeToFileNamed( $fullpath )

        Are you sure that you are looking at the correct file(s)? You also open $fh to append to $fullpath, which also strikes me as odd.

Re: Archive::Zip - zip files are corrupted or invalid
by amcglinchy (Novice) on Jul 12, 2011 at 16:55 UTC

    Although corruption like this will certainly occur on a Windows box, binmode should be optional (albeit good practice) on Linux.

    I had to do quite a bit of work to tidy up this code to make run though:

    • You are using >> to update your archive. Are you very sure you want to append?
    • Your "warn( print" style will see warnings printing "1" as this will likely be the result of the print

    I managed to massage your code into something that works (in 5.12.4) on linux without binmode. Also consider upgrading Perl as V5.8 is ancient. I would suggest trying to create a very simple example that zips up, and the unzips a single file. If that still fails, post your simplified code

Re: Archive::Zip - zip files are corrupted or invalid
by Anonymous Monk on Jul 12, 2011 at 16:03 UTC