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

I've written file uploaders before in CGI but I'm curious as how you would create a file downloader. My first idea was to use LWP::* but when I think about it, I don't think that's what the module was used for.

What's the simplest way to put in the url of a file and have it downloaded via the script? For now, it'll just download images. So if I put in $url = "www.page.com/images/image.gif"; it would save image.gif to my folder on the server.

This is how I created a file UPLOADER.

open( SAVED, ">>$localfile" ); while ( $bytesread = read( $remotefile, $buffer, 1024 ) ) { print SAVED $buffer; } close SAVED;

Replies are listed 'Best First'.
Re: File downloader
by tachyon (Chancellor) on Nov 12, 2004 at 23:29 UTC

    I am not sure if you mean use Perl to pull stuff from other servers:

    use LWP::Simple 'getstore'; my $url = 'http://some.domain.com/image.gif'; my $file = '/tmp/image.gif'; getstore( $url, $file );

    or if you mean do the opposite of a file upload, ie use a CGI script to control the downloading of certain images. If you don't want control you would just make them browsable. Anyway if you do a Super Search for 'CGI file download filename' in the text you will turn up all the info you need including:

    Web Initiated File Download
    File Download
    CGI File Download

    Incidentally when you open a file using >> you are opening it in APPEND mode, ie if it exists you add to the end of it. You almost certainly want > Also check the return value of the open and apply binmode as in:

    open F, ">$file" or die "Could not write $file Perl says reason $!\n"; binmode F; # may be important does no harm it not needed

    cheers

    tachyon

Re: File downloader
by pg (Canon) on Nov 13, 2004 at 03:59 UTC

    As tachyon and atcroft pointed out, you can use LWP::Simple. However I have a situation where I have to send cookie along with the request. In that case, LWP::Simple does not help any more, and I use LWP::UserAgent:

    use LWP::UserAgent; use HTTP::Request; use strict; use warnings; my $ua = LWP::UserAgent->new(); my $request = HTTP::Request->new(GET => "http://blah.com/attachmen +t.php?attachmentid=123"); $request->header("Cookie", 'a=1; b=2; c=3'); my $content = $ua->request($request)->content(); open(FILE, ">", "foo.jpg"); binmode(FILE); print FILE $content; close FILE;
Re: File downloader
by atcroft (Abbot) on Nov 12, 2004 at 23:30 UTC

    Look at LWP::Simple's getstore() function. To quote the documentation,

    getstore($url, $file) Gets a document identified by a URL and stores it in the file. The return value is the HTTP response code.

    Hope that helps.

Re: File downloader
by dave_the_m (Monsignor) on Nov 12, 2004 at 23:29 UTC
    My first idea was to use LWP::* but when I think about it, I don't think that's what the module was used for.
    Huh? That's the whole purpose of LWP. If your needs are simple, use LWP::Simple; if you want more control, use the other interaces that come with LWP.

    Dave.

Re: File downloader
by punch_card_don (Curate) on Nov 15, 2004 at 14:36 UTC
    Here is how I did something very similar for downloading PowerPoint files. I had a collection of PPT presentations and users could select which one they wished to download. Accept a form by cgi, get the name of the file requested, load the file, build any downlaod filename you like, return the appropriate disposition header, download the file.

    Disposition headers are very important when doing this. You can force the file to open in different ways. In this example, I'm forcing PPT to open the file in PPT outside of the browser and in slideshow mode. (If I recall correctly - it's a while since I looked at this system in action.)

    Obviously you'll write a much more elegant file-request-to-filename converter than the trash I've included here for this example.

    $presentation_1 = "./mypath/my_file_1"; $presentation_2 = "./mypath/my_file_2"; $presentation_3 = "./mypath/my_file_3"; $download_filetype = ".pps"; #get_and_process_form; my $query = new CGI; @form_field_names = $query->param; foreach $field (@form_field_names) { $form_values{$field} = $query->param($field); } $request = $form_values{'report'}; if ($request eq "aaaa") {$presentation = $presentation_1;} elsif ($request eq "bbbb") {$presentation = $presentation_2;} else {$presentation = $presentation_3;} open(FILE, $presentation) or dienice("cannot open file $presentation : + $_[0] $!"); @LINES = <FILE>; close(FILE); $filename = join('_', $form_values{'report'}, $form_values{'language'} +, $form_values{'year'}); $filename = join('', $filename, $download_filetype); print "Content-type: application/vnd.ms-powerpoint\n"; print "Content-Disposition: attachment; filename=$filename\n\n"; for $i (0..$#LINES) { print $LINES[$i]; }
Re: File downloader
by xorl (Deacon) on Nov 15, 2004 at 20:22 UTC
Re: File downloader
by Anonymous Monk on Nov 15, 2004 at 19:22 UTC

    Use the right tool for the job...if your needs are simple, just use wget or curl. These tools handle a lot of the cases that your code may or may not handle already, and they are robust, tested, etc.

    Not to discourage you from rolling your own, but for a simple task, I recommend tools that work already.