in reply to CRC Error on ZIP Files

Are you using warnings and strict? The code fragment you posted shows  use warnings; but the following suggests it's not used | there or has been disabled:

c:\@Work\Perl\monks>perl -wMstrict -le "my $index; $index == 0; ;; my @ra = qw(foo bar); print $ra[$index]; " Useless use of numeric eq (==) in void context at -e line 1. Use of uninitialized value $index in numeric eq (==) at -e line 1. Use of uninitialized value $index in array element at -e line 1. foo

use warnings; and  use strict; may help you find many instances of questionable code.

Another question comes to mind about the 'download' method you are using. If a text file is downloaded via a channel that automatically corrects line endings (e.g., cr-lf versus lf), the file will visually appear unchanged, but a binary file may be (almost certainly will be if it's big enough) corrupted. If you're using FTP, are you using ascii or binary mode?

Replies are listed 'Best First'.
Re^2: CRC Error on ZIP Files
by SearchigPerl (Acolyte) on Mar 01, 2014 at 17:34 UTC
    Hi AnomalousMonk,

    thanks for your reply !
    Warnings seem to be disabled somehow, since I am not receiving any of these
    when running the script. Yet I am aware of the fact, that I should use "strict".
    I must admit that I did not get rid of the bad habit of not declaring my
    variables throughout all these years ...

    To reply to your question: I think (!) I am not using FTP, since I am offering
    and sending the file through the recipients browser. For that I am switching binary
    mode on. Here is the critical code of the prescript running the download.

    sub download { use CGI; $html=new CGI; print $html->header(-type => 'application/octet-stream', -attachment = +> $_[1]); open($peunter, "<", $_[0].$_[1]); binmode($peunter); # while (read($pointer,$bytes,1024)) { # print $bytes; # } @data = <$peunter>; close($peunter); print "@data"; }

      If you are on Windows, you really need to

      binmode STDOUT;
      before printing. On all other operating systems, it's still good practice. Maybe try that, and alternatively, first create the ZIP file on disk, and manually download it through a trusted, different way, just to make sure that the ZIP file itself is not corrupted.

        Hi Corion,

        my deepest gratitude to you for your idea of testing the zip file on disk !
        I have been assuming the zip file itself would be generated wrongly. Now I
        realize it's not ! The zip file, prior to downloading is working perfectly fine. The
        problem lies within the download-script. Yet having added the command
        binmode STDOUT; did not alter anything.

      Apart from Corion's suggestion to include binmode STDOUT (which I think really might be an issue, even if it's not the only issue), you may also want to try:
      print $html->header(-type => 'application/zip', … );
      At least, according to Wikipedia, zip file format is "registered" as an official MIME type.

      Update: I actually don't know whether fixing the mime-type label will make any difference. I'm guessing that the issue is whether or not a carriage-return byte gets added before each line-feed byte, possibly at the receiving end, if not at the transmission end. Note the exact byte count for the original (working) zip file, then compare that to the exact byte count of a downloaded version; if the latter is bigger, there's something like a "unix2dos" filter kicking in at some point in the download process, and that will certainly screw up the zip file.

      print "@data";
      This is your problem. Consider this code:
      $ perl -E'@a=qw/1 2 3/; print "@a"' 1 2 3
      You wanted to print your lines joined by empty string, but "@array" joins array elements with space (read $" for more info on that). Your original, commented-out approach is better: just read your file by, say, 10 kilobytes and immediately send the data to client:
      { local $/ = \10240; print while <$peunter>; }
      In this example I tell Perl to read files with diamond operator (<$filehandle>) by 10240 bytes ($/) and loop printing the file pieces until I reach end-of-file.

      Edit: corrected typo
        Hi ww,
        thanks for your hint, I changed the code accordingly (although I believe to
        have understood that "octet-stream" would be valid for all formats).
        Yet with the altered code the problem remains.