Home > Archive > PERL CGI Beginners > September 2005 > Forcing a "save as' dialogue box to come up on left click
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
| Author |
Forcing a "save as' dialogue box to come up on left click
|
|
| Tony Frasketi 2005-09-18, 6:55 pm |
| Hello Listers
I'm trying to find a way to force a download dialogue box to come up
when the user clicks on a link on a web page (the link will primarily be
for htm, .txt files on the server). Normally when the user left clikcs
on the link the .htm or .txt file appears in the browser. And also
normally when the user right clicks on the link, he is given the choice
to 'Save Link Target as' in order to download the file.
What I'm looking for is to avoid right clicking and choosing to save the
file.... Is there a way to implement left clicking the link and
automatically bringing up a "Save As" dialogue box?
I've googled for such things as "mime type download save as.... etc" but
came up with dead ends....
TIA
Tony Frasketi
| |
| Chris Devers 2005-09-18, 6:55 pm |
| | |
| Tony Frasketi 2005-09-18, 9:55 pm |
|
Chris Devers wrote:
>What have you tried so far?
>
>
>
I've tried two approaches so far.
1) An ftp://.... Link but that reqired a user ID and password. Nix to
that !
2) <meta http-equiv=refresh content="3; url=xxxx.zip> in the header
section of the web page which I obtained from....
http://www.dtp-aus.com/dwnloads.htm.
This did not work as advertised. This web page also suggested using a
CGI script which is called in place of the actual file name (the link is
changed) and having the script "organize" the "redirected" URL (not sure
what this means). But I haven't tried this yet. I'm not quite sure what
the CGI script would have to do... Probably ought to investigate this
some more.
I will look around for some javascripts as you suggested. I'm currently
using Mozilla 5.0 suite, I suppose Firefox amounts to the same thing as
far as this topic goes.
I would have thought this feature would have certainly been worked out
by this time....
Thanks for the response
Tony Frasketi
| |
| Wiggins d'Anconia 2005-09-18, 9:55 pm |
| Tony Frasketi wrote:
> Hello Listers
> I'm trying to find a way to force a download dialogue box to come up
> when the user clicks on a link on a web page (the link will primarily be
> for htm, .txt files on the server). Normally when the user left clikcs
> on the link the .htm or .txt file appears in the browser. And also
> normally when the user right clicks on the link, he is given the choice
> to 'Save Link Target as' in order to download the file.
>
> What I'm looking for is to avoid right clicking and choosing to save the
> file.... Is there a way to implement left clicking the link and
> automatically bringing up a "Save As" dialogue box?
>
> I've googled for such things as "mime type download save as.... etc" but
> came up with dead ends....
>
> TIA
> Tony Frasketi
>
Most browsers will provide this functionality if the return header is
"application/octet-stream" rather than "text/html" or the like. In the
case of IE you may have to fool the browser into thinking it is getting
something different than it is based on the URL, because it likes to
look there for a file extension to determine the file type too.
HTH,
http://danconia.org
| |
| Tony Frasketi 2005-09-18, 9:55 pm |
| Wiggins d'Anconia wrote:
> Most browsers will provide this functionality if the return header is
> "application/octet-stream" rather than "text/html" or the like. In
> the case of IE you may have to fool the browser into thinking it is
> getting something different than it is based on the URL, because it
> likes to look there for a file extension to determine the file type too.
> HTH,
> http://danconia.org
>
Hi Wiggins
Thanks... I just tried putting these three lines in a .htaccess file in
a particular directory...
AddType application/octet-stream .cgi
AddType application/octet-stream .txt
AddType application/octet-stream .htm
Alternatively, I also tried AddType application/octet-stream .cgi
..txt .htm
Using the Mozilla 5.0 Suite browser, I get the following results....
And then trried clicked on links to a .cgi file, a .txt file, and a .htm
file in that directory.... Only the .htm file automaticaly brought up a
'Save as...' diaglogue box as I left clicked on the link to the .htm file
when I clicked on the link to the .txt file, the contents of the .txt
file appeared in a Wordpad window.
When I clicked on the link to the .cgi file, the .cgi file was executed
and the results displayed in the browser window.
One out of three right!
----------------------------
Using the Microsoft IE 6.0 browser, I get the following results....
..htm file -> Displays the .htm file in browser window
..txt file -> Displays the .txt file in browser window
..cgi file -> Executes the .cgi script and displays results in browser window
zero out of three right!
----------------------------
Using Firefox 1.0 browser, I get the following results...
..htm file -> brings up the 'Save as...' dialogue box
..txt file -> brings up the 'Save as...' dialogue box
..cgi file -> Executes the .cgi script and displays results in browser window
SO....................... Filefox wins by getting two out of the three
right!
This method doesn't look very hopeful at this point!
Thanks again
Tony Frasketi
| |
| David Dorward 2005-09-19, 3:55 am |
| On Sun, 2005-09-18 at 17:46 -0500, Tony Frasketi wrote:
> I'm trying to find a way to force a download dialogue box to come up
> when the user clicks on a link on a web page
http://www.faqs.org/rfcs/rfc2183.html
--
David Dorward <http://dorward.me.uk/>
"Anybody remotely interesting is mad, in some way or another."
-- The Greatest Show in the Galaxy
| |
| Tony Frasketi 2005-09-19, 6:55 pm |
| Thanks for the response, David.
I scanned thru the document to which you refer and from what I can
understand it appears 'to me' that the 'Content-Disposition Header
Field" being described is in the context of email messages. Can you give
me some more information as to whether this can apply to downloads of
any type of files (.htm, .txt, .dump, etc...)from a link on a web site
page and will force the browser to put up a 'Save as' dialogue box.
Perhaps an simple example of how you would use this field to accomplish
this? I'm afraid my lack of experience here prevents me from proceeding
further...
TIA
Tony Frasketi
David Dorward wrote:
>On Sun, 2005-09-18 at 17:46 -0500, Tony Frasketi wrote:
>
>
>
>http://www.faqs.org/rfcs/rfc2183.html
>
>
>
| |
| Wiggins d'Anconia 2005-09-19, 6:55 pm |
| Tony Frasketi wrote:
> Wiggins d'Anconia wrote:
>
> Hi Wiggins
> Thanks... I just tried putting these three lines in a .htaccess file in
> a particular directory...
>
> AddType application/octet-stream .cgi
> AddType application/octet-stream .txt
> AddType application/octet-stream .htm
>
> Alternatively, I also tried AddType application/octet-stream .cgi
> .txt .htm
>
Interesting way to do it, not what I intended. Have you 100% confirmed
that the header is being passed back correctly? I am not sure how Apache
(or whatever web server you are using) handles setting the type, it
might be finding it from somewhere else that is overriding it. There is
a module for Firefox/Mozilla called "Live HTTP Headers" that will help
you confirm what is being sent.
What I was intending was to call the cgi script and rather than it
printing the normal text/html header it would print the header directly,
that way you are guaranteed to be operating the way you intended.
> Using the Mozilla 5.0 Suite browser, I get the following results....
>
> And then trried clicked on links to a .cgi file, a .txt file, and a .htm
> file in that directory.... Only the .htm file automaticaly brought up a
> 'Save as...' diaglogue box as I left clicked on the link to the .htm file
>
> when I clicked on the link to the .txt file, the contents of the .txt
> file appeared in a Wordpad window.
This is windows picking up the association based on the extension
(probably), didn't you know it was smarter than you? ;-)
>
> When I clicked on the link to the .cgi file, the .cgi file was executed
> and the results displayed in the browser window.
>
> One out of three right!
>
> ----------------------------
> Using the Microsoft IE 6.0 browser, I get the following results....
>
> .htm file -> Displays the .htm file in browser window
> .txt file -> Displays the .txt file in browser window
> .cgi file -> Executes the .cgi script and displays results in browser
> window
>
> zero out of three right!
Yeh I suspect that is IE picking up on the URL extension.
>
> ----------------------------
> Using Firefox 1.0 browser, I get the following results...
> .htm file -> brings up the 'Save as...' dialogue box
> .txt file -> brings up the 'Save as...' dialogue box
> .cgi file -> Executes the .cgi script and displays results in browser
> window
>
The .cgi problem is probably because you have a handler setup for .cgi
files that trumps the AddType call. What is the header printed by the
..cgi file? It should be able to print its own header of
"application/octet-stream" followed by the contents of a "file" and it
should work correctly.
> SO....................... Filefox wins by getting two out of the three
> right!
>
> This method doesn't look very hopeful at this point!
I know I have used this method before, and I have done so recently from
within the context of a different web framework (specifically Interchange).
As to your question about "Content-Disposition" it can be used to preset
the filename that the user sees in the "Save as..." dialogue, but is
again not standard, it is just convention and will depend on the browser
supporting it, to my knowledge the major browsers[1] do support it.
> Thanks again
> Tony Frasketi
Keep at it, I suspect you will get it to work...
http://danconia.org
[1] When I say major browsers I mean Mozilla (and variants, Firefox,
etc.), IE (some recent version, probably newer than 4.x), Safari. I know
there are others but I don't have a copy so can't say specifically how
they act, they may work as well.
| |
| Tony Frasketi 2005-09-19, 9:55 pm |
|
> What I was intending was to call the cgi script and rather than it
> printing the normal text/html header it would print the header directly,
> that way you are guaranteed to be operating the way you intended.
Hi Wiggins
Thanks for this suggestion... I've tried the following bit of CGI script
with three different file types (.txt, .cgi, .dat) and in each case *DO*
get the 'Save as...' dialogue box to come up and when I select 'Save to
disk' and click ok, It appears as if a transfer occurs but only a
zero-length file is saved to my local hard disk directory. The code is
as follows...
========================================
====================================
#!/usr/local/bin/perl -w
# testoctetstream_1.cgi
# My base directory and base directory URL
my($basedir) = "<base directory>";
my($baseurl) = "<base URL>";
# Location of the file to be downloaded
$fileloc = "$basedir/cgi-bin/test/xxx.txt";
#$fileloc = "$basedir/cgi-bin/test/testdu1.cgi";
#$fileloc = "$baseurl/cgi-bin/test/testdu.dat";
# Name of file to be downloaded
$filename = "xxx.txt";
#$filename = "testdu1.cgi";
#$filename = "testdu.dat";
# NOTE: Uncomment the desired $filename and $fileloc above
# Set The headers
print "Content-Type: application/octet-stream;\n";
print "Content-Disposition: attachment; filename=\"$filename\"\n";
# ---------------------------------------------------------------
# Note: Can't figure out what to put in here to actually download
# the darn file!!!
# ---------------------------------------------------------------
print "\n";
exit;
========================================
====================================
The above cod was tested in both Mozilla and IE browers with the same
results.
It appears I'm missing some statement that should follow the
Content-Disposition
statement.
I've read the RFC 1806 document
(http://www.faqs.org/rfcs/rfc1806.html) which provided several examples
as shown below. Both examples are transferring a .jpg file and indicates
that the .jpg file's data is to immediately follow the Content-xxxxx
statments.... This is not what
I'm looking for... What I need is a statement that will get the data
from the
file that I'm trying to transfer...
========================================
=====================================
2.6 Content-Disposition and the Main Message
It is permissible to use Content-Disposition on the main body of an
[RFC 822 <http://www.faqs.org/rfcs/rfc822.html>] message.
3. Examples
Here is a an example of a body part containing a JPEG image that is
intended to be viewed by the user immediately:
Content-Type: image/jpeg
Content-Disposition: inline
Content-Description: just a small picture of me
<jpeg data> <----------------------- ****
The following body part contains a JPEG image that should be
displayed to the user only if the user requests it. If the JPEG is
written to a file, the file should be named "genome.jpg":
Content-Type: image/jpeg
Content-Disposition: attachment; filename=genome.jpeg
Content-Description: a complete map of the human genome
<jpeg data> <----------------------- ****
========================================
=====================================
Hopefully you can come up that missing statement that will perform the
magic
I'm looking for or suggest somewhere else to look.....
Thanks again
Tony Frasketi
| |
| Tony Frasketi 2005-09-19, 9:55 pm |
| Wiggins d'Anconia wrote:
<Clip>
>
>Interesting way to do it, not what I intended. Have you 100% confirmed
>that the header is being passed back correctly? I am not sure how Apache
>(or whatever web server you are using) handles setting the type, it
>might be finding it from somewhere else that is overriding it. There is
>a module for Firefox/Mozilla called "Live HTTP Headers" that will help
>you confirm what is being sent.
>
><clip>
>
>
Hi Wiggins.
I tried your suggestion to confirm what the header being sent is via...
http://web-sniffer.net/
And it looks like what I'm intending to send out is being sent out....
Just ain't sending enuff, I reckon...
Tony.
P.S. By the way, I previously have tried determining the length of the
file to be sent and setting Content-Length to $filesize. But that didn't
seem to make a difference...
========================================
=================================
HTTP Request Header
Connect to 65.254.228.100 on port 80 ... ok
GET /cgi-bin/test/testoctetstream.cgi HTTP/1.1[CRLF]
Host: spacecovers.com[CRLF]
Connection: close[CRLF]
Accept-Encoding: gzip[CRLF]
Accept:
text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5[CRLF]
Accept-Language: en-us,en;q=0.5[CRLF]
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7[CRLF]
User-Agent: Mozilla/5.0 (Windows; U; Win 9x 4.90; en-US; rv:1.7.8)
Gecko/20050511 Web-Sniffer/1.0.22[CRLF]
Referer: http://web-sniffer.net/[CRLF]
[CRLF]
HTTP Response Header
Name Value Delim
HTTP Status Code: HTTP/1.1 200 OK
Date: Tue, 20 Sep 2005 00:01:33 GMT CRLF
Server: apache CRLF
Content-Disposition: attachment; filename="testdu.dat" CRLF
http: //spacecovers.com/cgi-bin/test/testdu.dat CRLF
Content-Length:
CRLF
Connection: close CRLF
Content-Type: application/octet-stream; CRLF
========================================
=================================
| |
| Wiggins d'Anconia 2005-09-19, 9:55 pm |
| Tony Frasketi wrote:
>
>
> Hi Wiggins
> Thanks for this suggestion... I've tried the following bit of CGI script
> with three different file types (.txt, .cgi, .dat) and in each case *DO*
> get the 'Save as...' dialogue box to come up and when I select 'Save to
> disk' and click ok, It appears as if a transfer occurs but only a
> zero-length file is saved to my local hard disk directory. The code is
> as follows...
Ok, so almost there.... let's back up a step and understand the whole
thing. The HTTProtocol is very similar to other common net protocols
where there is a header section and a data (or payload) section. The two
are separated by a blank line. So right now you are providing the header
(apparently correctly). The client reads that information and based on
what it knows how to handle it decides on a way to use the payload. In
this case we are giving the browser less than optimal descriptors of the
payload. Basically we are telling it that there is something coming and
that neither I nor you know what it is. So it does the only thing it
can, "Save as...". The only hint you are providing it a suggestion about
what to call that thing. So right now you are providing a header, but
not a payload, let's add it....
> ========================================
====================================
>
> #!/usr/local/bin/perl -w
>
> # testoctetstream_1.cgi
>
> # My base directory and base directory URL
> my($basedir) = "<base directory>";
> my($baseurl) = "<base URL>";
>
> # Location of the file to be downloaded
> $fileloc = "$basedir/cgi-bin/test/xxx.txt";
> #$fileloc = "$basedir/cgi-bin/test/testdu1.cgi";
> #$fileloc = "$baseurl/cgi-bin/test/testdu.dat";
>
> # Name of file to be downloaded
> $filename = "xxx.txt";
> #$filename = "testdu1.cgi";
> #$filename = "testdu.dat";
>
> # NOTE: Uncomment the desired $filename and $fileloc above
>
> # Set The headers
> print "Content-Type: application/octet-stream;\n";
> print "Content-Disposition: attachment; filename=\"$filename\"\n";
>
> # ---------------------------------------------------------------
> # Note: Can't figure out what to put in here to actually download
> # the darn file!!!
> # ---------------------------------------------------------------
>
This is the simple part, and probably looks a little like.
open file...
read in file...
print file back to browser...
close file
There are simpler ways to do this, but what I have come to use looks like:
my $READHANDLE;
unless (open $READHANDLE, $file) {
# error handling...
}
binmode $READHANDLE;
$| = 1;
while ( my $length = sysread $READHANDLE, my $buffer, $block_size ) {
next unless defined $length;
my $offset = 0;
while ( $length ) {
my $written = syswrite STDOUT, $buffer, $length, $offset;
$length -= $written;
$offset += $written;
}
}
close $READHANDLE;
> print "\n";
You will want to remove this as it will be an addition to the actual
data which can break some formats.
> exit;
> ========================================
====================================
>
> The above cod was tested in both Mozilla and IE browers with the same
> results.
>
>
> It appears I'm missing some statement that should follow the
> Content-Disposition
> statement.
>
Does this hit the mark?
http://danconia.org
| |
| David Dorward 2005-09-20, 7:55 am |
| On Mon, Sep 19, 2005 at 09:36:16AM -0500, Tony Frasketi wrote:
> Thanks for the response, David.
> I scanned thru the document to which you refer and from what I can
> understand it appears 'to me' that the 'Content-Disposition Header
> Field" being described is in the context of email messages.
Whoops, beg pardon.
http://www.faqs.org/rfcs/rfc2616.html
Section 19.5.1
--
David Dorward http://dorward.me.uk
| |
| Bob Showalter 2005-09-20, 7:55 am |
| Tony Frasketi wrote:
> Hello Listers
> I'm trying to find a way to force a download dialogue box to come up
> when the user clicks on a link on a web page (the link will primarily
> be for htm, .txt files on the server).
Short answer is that you cannot *force* the client to do anything.
The HTTP standard addresses this in sec. 19.5.1 of RFC 2616, so you should
read that over. Unfortunately, not all clients follow the standard here.
| |
|
| Hi all,
Did you read it?
Content-Disposition -> "do not enclose filenames in quotes"
http://support.microsoft.com/kb/q182315/
Thanks,
Sara.
----- Original Message -----
From: "Wiggins d'Anconia" <wiggins@danconia.org>
To: "Tony Frasketi" <webmaster@spacecovers.com>
Cc: <beginners-cgi@perl.org>
Sent: Tuesday, September 20, 2005 5:22 AM
Subject: Re: Forcing a "save as' dialogue box to come up on left click
> Tony Frasketi wrote:
>
> Ok, so almost there.... let's back up a step and understand the whole
> thing. The HTTProtocol is very similar to other common net protocols
> where there is a header section and a data (or payload) section. The two
> are separated by a blank line. So right now you are providing the header
> (apparently correctly). The client reads that information and based on
> what it knows how to handle it decides on a way to use the payload. In
> this case we are giving the browser less than optimal descriptors of the
> payload. Basically we are telling it that there is something coming and
> that neither I nor you know what it is. So it does the only thing it
> can, "Save as...". The only hint you are providing it a suggestion about
> what to call that thing. So right now you are providing a header, but
> not a payload, let's add it....
>
>
> This is the simple part, and probably looks a little like.
>
> open file...
> read in file...
> print file back to browser...
> close file
>
> There are simpler ways to do this, but what I have come to use looks like:
>
> my $READHANDLE;
> unless (open $READHANDLE, $file) {
> # error handling...
> }
> binmode $READHANDLE;
>
> $| = 1;
>
> while ( my $length = sysread $READHANDLE, my $buffer, $block_size ) {
> next unless defined $length;
>
> my $offset = 0;
> while ( $length ) {
> my $written = syswrite STDOUT, $buffer, $length, $offset;
> $length -= $written;
> $offset += $written;
> }
> }
>
> close $READHANDLE;
>
>
> You will want to remove this as it will be an addition to the actual
> data which can break some formats.
>
>
> Does this hit the mark?
>
> http://danconia.org
>
> --
> To unsubscribe, e-mail: beginners-cgi-unsubscribe@perl.org
> For additional commands, e-mail: beginners-cgi-help@perl.org
> <http://learn.perl.org/> <http://learn.perl.org/first-response>
>
>
| |
|
|
| Tony Frasketi 2005-09-20, 6:57 pm |
|
Sara wrote:
> Hi all,
>
> Did you read it?
>
> Content-Disposition -> "do not enclose filenames in quotes"
>
> http://support.microsoft.com/kb/q182315/
>
> Thanks,
> Sara.
>
Thanks very much for the info, Sara ! Will try it without the quotes!
Tony Frasketi
| |
| Tony Frasketi 2005-09-20, 6:57 pm |
| Wiggins d'Anconia wrote:
[color=darkred]
-----------------------------------------------------------
Hello Wiggins
I'm very grateful for your help - I finally have a working version of a
CGI script which will allow me to selecte files simply by clicking on a
'download' icon which is what I was after for some special purpose web
pages for site maintenance.
Below is the final script I came up with which performs the actual file
download.....
========================================
================================
#!/usr/local/bin/perl -w
# -----------------------------------------------------------------
# filedownload.cgi - Downloads a file
#
# Designed to be executed by clicking on a webpage link or an icon
#
# <a href="...filedownload.cgi?filepath=<filepath>arbitrary text</a>
#
# 2005/09/19 - Original coding
#
# Note: This script based primarily on suggestions given by
# Wiggins d'Anconia at wiggins@danconia.org
#
# Notes: http://support.microsoft.com/kb/q182315/ says not to use
# quote marks for filename in Content-Disposition statement
# -----------------------------------------------------------------
use strict;
use diagnostics;
my($basedir) = "<base directory>";
my($baseurl) = "http://spacecovers.com";
my($filepath) = $ENV{QUERY_STRING};
$filepath = '' if(!$filepath);
# add basedir to filepath if it has none
if($filepath !~ m!^$basedir!i) {
print "basedir not found<br>";
$filepath = "$basedir/$filepath";
}
# convert double /'s to single /.
$filepath =~ s!//!/!i;
# Get just the filename from the path
my($filename) = $filepath;
$filename =~ s!^(.+/)(.+)$!$2!i;
# Read file in binary mode
my($buffer) = &read_file_binary($filepath);
# Set headers
print "Content-Type: application/octet-stream;\n";
print "Content-Disposition: attachment; filename=$filename\n";
print "\n";
# download the file's contents
print $buffer;
exit;
# ----------------------------------------------------------------
# Read the file in binary mode
# $buffer = &read_file_binary($filename);
# ----------------------------------------------------------------
sub read_file_binary {
my($filename) = @_;
my($var) = '';
# Open the file in binary mode
if(!open(FILE,$filename)) {
print "Content-type: text/html\n\n";
print "Can't open file [$filename]<br>";
exit;
}
binmode(FILE);
# Read in the file
while (<FILE> ) {
$var .= $_;
}
# close the file and return its contents
close(FILE);
return $var;
}
========================================
================================
Please excuse the code. It most likely could be optimized and provide more
error checking but its the best I know how to do at present. However, I'm
always open to suggestions on better ways to do things.
I've tested the script using Mozilla 5.0, Firefox 1.0, IE 6.0, and even
the ancient Netscape 4.7 (horrors!). The test program I used is at....
http://spacecovers.com/cgi-bin/test...iledownload.htm
and it tests various sizes of files and the following file types (.htm,
..txt, and .cgi).
In those browsers tested, the results were similar. All came up with a
'File Download' dialogue box (although different flavors). I think I
need to do some further testing on different file types (e.g., .exe,
..zip, .jpg, etc...) But that will have to wait till a bit later.
I want to thank everyone who responded to my posting. I think this is a
great group. Many seasoned programmers willing to help those of us with
less experience.
Thank you.....
Tony Frasketi
|
|
|
|
|