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

I am trying to build an automated system where a member can download any file that we have for them, we may have any type of file, examples may include:

pdf
gif
jpg
html
csv
txt
php
cgi
.zip
.tar

so, they could be binary files or they may be ascii only files. My question is this, since I want to count how many times the file is downloaded, when I print the file to the browser as an attachment, how do I know if I need to buffer the data or not?

I am using File::MimeInfo but I don't see how that can tell me if the file is binary or not...

Since I want this to be automated, I don't want to have to just check the extension for file I know for sure we will use, I want it to be automated so no matter what files we put there, it will work... like the list above does not include .psd, what if we wanted to add that one? if we have to hard code each different check, then we limit ourselves.

I would appreciate any pointers for this.

Richard

Replies are listed 'Best First'.
Re: printing file downloads
by Anonymous Monk on Dec 23, 2010 at 02:22 UTC
    when I print the file to the browser as an attachment, how do I know if I need to buffer the data or not?

    You don't need buffering so you can turn it off, or you can close STDOUT (assuming this is under CGI protocol) and that will flush the buffers (and under CGI protocol, signal your webserver your CGI program is finished sending data)

    I am using File::MimeInfo but I don't see how that can tell me if the file is binary or not...

    All files are binary, even text files, esp where HTTP is concerned

    I would appreciate any pointers for this.

    It is simplest to let your webserver serve files, and then parse the logs for stats, but if you wish to do it from your program, don't forget to read relevant rfcs and write support for resuming/range feature

      so if I just open the file I can print it like this:
      my $file = "/path/to/file.pdf"; use File::MimeInfo; my $mime_type = mimetype($file); print header(-type => "$mime_type", -Content_disposition => qq(attachm +ent; filename="file.pdf")); open(OUTF,"$file"); while(<OUTF>) { print $_; } close(OUTF); exit;
      Then that will work?
      I thought if it was a binary file I had to do something with binmode or something?

      It has been a long time since I have learned all that, a very long time, so I do not remember the correct ways to do it, thus I am here for the wisdom of all you perl monks...

      Sorry if that sounded like brown nosing ;o), was not meant to, just trying to get this figured out.

      Thanks again,
      Richard
        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.