in reply to Web Initiated File Download

From this Microsoft article:

When you serve a document from a Web server, you might want to immediately prompt the user to save the file directly to the user's disk, without opening it in the browser. However, for known MIME (Multipurpose Internet Mail Extensions) types such as Microsoft Word ("application/ms-word"), the default behavior is to open the document in Internet Explorer.

You can use the content-disposition header to override this default behavior. Its format is:


Content-disposition: attachment; filename=fname.ext 

You can also read RFC 1806 which may give you more information. According to the RFP, you don't specify the filename with an "inline" content-disposition. Further, "inline" is designed to render the data directly rather than prompt for a dialog box, which is what your issue appears to be. I'd try the following untested code (note that I am passing the MIME type rather than hard-coding it):

sub download_file { my ( $filename, $mime ) = @_; if ( ! -e $filename ) { croak "$filename does not exist": } my $filesize = -s $filename; # print full header print "Content-disposition: attachment; filename=$filename\n"; print "Content-Length: $filesize\n"; print "Content-Type: $mime\n\n"; # open in binmode open READ, "< $filename" or croak "Cannot open $filename for r +eading: $!"; binmode READ; # stream it out binmode STDOUT; { local $/; print <READ>; } close(READ); # should always return true return(1); }

Cheers,
Ovid

Vote for paco!

Join the Perlmonks Setiathome Group or just click on the the link and check out our stats.

Replies are listed 'Best First'.
Re: (Ovid) Re: Web Initiated File Download
by THRAK (Monk) on Sep 07, 2001 at 19:16 UTC
    Ovid, thanks. Working from your code snippet I rolled it into the code below. Changed it to use CGI header generation and also passing a default file name. Probably not good for everyone, but works well for what I'm doing. This worked in both IE5.5 & NS4.7x when I pass it a MIME of $mime_type = "text/tab-separated-values\; charset=us-ascii";
    One question, what does the localization of $/ do? I understand what they do independently, but why is this necessary?
    sub download_file { # REF: http://www.perlmonks.org/index.pl?node_id=110714&lastnode_id +=3628 my ( $send_file, $send_name, $mime ) = @_; die "$send_file does not exist." unless ( -e $send_file ); my $filesize = -s $send_file; print $query->header(-type=>$mime, -Content_disposition=>"attachment; fil +ename=$send_name", -Content_Length=>"$filesize" ); # open in binmode open READ, "< $send_file" or die "Cannot open $send_file for readi +ng: $!"; binmode READ; binmode STDOUT; # stream it out { local $/; print <READ>; } close(READ); return(1); # should always return true }


    -THRAK
    www.polarlava.com

      THRAK asked:

      What does the localization of $/ do?

      As you probably know, $/ is the input record separator. Typically, this is set to the newline on the system the program runs on. This causes records to be read in "one line" at a time. However, since you intend to send all of this data straight to the browser, I thought it would be more efficient to use "slurp mode". By using local $/, the input record separator is undef and this causes the print to send the entire file without needing a while loop. However, I put $/ in its own scope to ensure that it would not clobber whatever value it had originally been set to, since this is a global variable.

      Cheers,
      Ovid

      Vote for paco!

      Join the Perlmonks Setiathome Group or just click on the the link and check out our stats.