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

Here's something that has bothered me for a while.. When I want a CGI script to send the user a file it has generated, I have no problem getting it to send the file and make a browser try to save it to disk (giving it a header mimetype of "application/binary" usually does the trick) but the browser always wants to save the file as "whatever.cgi". Is there any way to specify a different default filename, or at least a different extension? I've looked through my CGI.pm docs but haven't found anything along these lines.

--I write the code while the master is away!

Comment on
Getting CGI to name a file it returns
Replies are listed 'Best First'.

Another way to do it is to use the Content-Disposition header. Set the mimetype to "application/octet-stream", then add a header like this: "Content-Disposition: inline;filename=$filename\n". Be sure to set the "Content-Length" header as well.

inline;filename=$filename is exactly how I did things in this thread. It works great. When the user is first prompted to save the file, it says whatever.cgi, but when they click save (insted of "open from..") it has the correct file name ($filename).

Most servers (read: apache) don't try for the full path but instead descend level by level down the URL until they find something meanful (and grabbing .htaccess files along the way). When it reaches the mycgi.pm level, it passes the remaining URL ("/myfile.txt?file=myfile.txt") info into a variable (I believe in $QUERY_STRING, but I can't verify this at the moment); CGI.pm will typically ignore the stuff until the '?', at which point it does it's own parsing.
I'm about 99% sure meryln has a column on how to use virtual file structure information in a CGI statement.

On the browser side, most browsers look at the last 'filename' before the '?' as what the page should be saved as, so in the URL above, the browser would try to save this as myfile.txt. Note, however, this is a browser-dependant feature, though the 3 major ones (IE, NS, Opera) all do it this way.

So all you need to do is to make sure that the form that is used to generate this page has the appropriate extra file information in the FORM ACTION field.

usually putting (uh... memory slipping...) false file information after the actual path will do the trick.
so rather than
http://foo.com/cgi-bin/bar.cgi
have
http://foo.com/cgi-bin/bar.cgi/baz.doc
and most browsers will save the script's output as baz.doc. This trick should not affect the execution of your script under Apache or IIS.

what the heck is application/binary ? It's probably better to use application/octet-stream, which is an accepted MIME type (though it doesn't mean much).

And it's more likely that someone will have defined a handler for an accepted MIME type. For instance, I have one handler in my browser for application/octet-stream, and another handler for unknown MIME types. And they're different.

One thing I've noticed with
Content-type: application/octet-stream is that certain
browsers will still try and load the file in the browser
instead of thowing up a save as dialog. (Certain versions
of IE will do this.) I usually use application/unknown,
although I'm not sure that it's 100% successful.

Sure octet-stream means something. It means that the output should
be read as a stream of octets rather than a stream of binary
and that you should be able to rely on recieving an even set
of octets rather than an number of bits that doesn't resolve to an even octet. Of course, this is imposed by the IP protocol, so anything that comes down the pipe is technically an "octet-stream." It could be an indication that the content is not to be interpretted with split bytes (which IS done elsewhere) and that it is probably not plaintext.

Another trick that sometimes works but one that I would
not suggest is to play with the filename of your script,and in like say in .htaccess (with apache) set your handler for .doc as a cgi-script etc etc ...
Brought to you by that crazy but lovable guy... lindex