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

I have a directory on my server not visible from the web. Is their a way that I can open one of the files in this directory, and send that to the browser as a file download? I don't want these files downloadable, unless you go through the proper procedure of using the perl script... Thanks

Replies are listed 'Best First'.
Re: Download Files Server by PERL?
by davorg (Chancellor) on Oct 16, 2001 at 18:49 UTC

    Write a CGI script that:

    • Opens the required file.
    • Reads the file and writes the contents to STDOUT

    Don't forget to write the correct Content-type header.

    --
    <http://www.dave.org.uk>

    "The first rule of Perl club is you don't talk about Perl club."

      Yes as davorg suggests just dumping the file to STDOUT from the script is enough.

      Beware of the security implications though.
      Make sure your script will not open just any file it is asked to.
      You don't want some kid typing: www.myserver.org/myscript.pl?file=../../../etc/passwd or some such thing !!!
Re: Download Files Server by PERL?
by slayven (Pilgrim) on Oct 16, 2001 at 19:22 UTC
    as davorg mentioned, this would be a good solution.
    just to remind you of two problems that may occur:

    try putting Content-Disposition: infile; filename=$filename into the header if the browser doesn't know, what filename it should choose for saving the file

    binmode STDOUT; is usefull, if you transfer binary data
Re: Download Files Server by PERL?
by dvergin (Monsignor) on Oct 16, 2001 at 19:29 UTC
    Here's a bit of working code snipped from a larger script that may help you get started. You'll need to supply some values and do some rewriting (for example, it looks to me like some of the needed 'my' statements preceed this snippet)...

    # First set up a few values for the download header my ($sec, $min, $hr, $day, $mon, $yr, $wday) = (gmtime()); $sec = sprintf("%2.2d", $sec ); $min = sprintf("%2.2d", $min ); $hr = sprintf("%2.2d", $hr ); $day = sprintf("%2.2d", $day ); $yr = sprintf("%4.4d", ($yr+1900)); $mon = ('Jan','Feb','Mar','Apr','May','Jun', 'Jul','Aug','Sep','Oct','Nov','Dec')[$mon]; $wday = ('Sun','Mon','Tue','Wed','Thu','Fri','Sat')[$wday]; my $server = $ENV{SERVER_SOFTWARE}; $server =~ s/^(\S+)//; # #. . . omitted some code here # # Now do the download open DOWNLOAD, "<$upload_dir/$dir/$filename" or die "Can't open $upload_dir/$dir/$filename\n"; my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev, $size,$atime,$mtime,$ctime,$blksize,$blocks) = stat DOWNLOAD; print "Date: $wday, $day $mon $yr $hr:$min:$sec GMT\n"; print "Server: $server\n"; print "MIME-version: 1.0\n"; print "Content-type: $content_type\n"; print "Content-length: $size\n"; print "\n"; binmode STDOUT; while (read(DOWNLOAD, $buffer, $buffer_size)) { print $buffer; } close DOWNLOAD;
    Also, take koo's comment very seriously. Make sure you have a robust mechanism for screening what can be downloaded.

    Hope this helpes.