in reply to Re^2: printing file downloads
in thread printing file downloads

I don't know the CGI specifics, but yes if you want to output binary info (and all files can be output as a direct binary copy of the file), something like this (code snippet that I had laying around from long ago):
open(my $inbin, '<', $infile) || die "unable to open $infile"; binmode($inbin) || die "unable to set binmode $infile; open (my $outbin, '>', $outfile) || die "unable to open $outfile"; binmode($outbin) || die "unable to set binmode $outfile"; while (read($inbin, my $buff, 8 * 2**10)) { print $outbin $buff; } close($inbin) || die("unable to close $infile"); close($outbin) || die("unable to close $outfile");
print will know how may bytes of the possible 8K are used in the $buff and that many bytes are output. In your case, you are using STDOUT, I think you also have to close it like I did in the file -> file version. Besides flushing any intermediate stuff, also says "EOF". There might be some alternate way when dealing with STDOUT. There are unbuffered versions, sysread and syswrite, I would read the man pages carefully. Don't mix buffered and non-buffered output to the same file handle.

You asked another question, don't know if it is relevant given the above, but for example on Unix, the way that the binary file test operator works, is that the file is opened and some amount of the file is read - there is an algorithm to decide whether this is a binary file or not. Anyway, you have the file, and you can just to a -b test on it, if that was of interest. However with an attachment, you may not care.

PS: I don't know how setting binmode could fail, but I just kept that stuff when I copied and pasted. I don't think the die message is necessary.

Replies are listed 'Best First'.
Re^4: printing file downloads
by Anonymous Monk on Dec 23, 2010 at 18:06 UTC
    see that is my problem, I need to find out if I have to print a binary file or not, so is there a way to check if the file is a binary file or a text file? something like this:

    my $filename = "file.gif"; my $filepath = "/path/to/"; if(-e "$filepath$filename") { my $_binCheck = is_file_binary("$filepath$filename"); if($_binCheck && $_binCheck == 1) { # print header for download and then open the file in binary mode +and print to window for the attachment } else { # print header for download and open the file normally and print t +o window for the attachment } } else { die "File does not exist: $filepath$filename"; }
    That is what I need to do, is tell if the file is binary or text so I can print the correct way.

    Anyone know the best way to do that?

    Thanks,
    Richard
      I see that you understand that there is a -e "exists" file test operator, also there is:
      -T is a text file
      -B is a binary file (opposite of -T)

      If you are going to continue writing Perl, I strongly recommend that that you buy a copy of the language reference manual, Programming Perl by Larry Wall, et. al. In my 3rd edition, page 98 lists a whole slew of these file test operators so many that I can't count at a glance.

      if(-B "$filepath$filename"){...file is Binary...}
      However, as has been pointed out... ALL files can be sent as faithful copies of the binary bits.
      see that is my problem, I need to find out if I have to print a binary file or not

      I already covered this, there is absolutely no reason you need to find out, treat them all as binary, print the appropriate headers, and let the browser do its job

        sure enough, I tested it with a .gif and even though I did not set binmode it worked great... You were right.

        I did not understand that when you said it, I was working on no sleep in 19 hours so I was very tired... anyhow, it works great now.

        Thank you all for helping me resolve this.

        Richard