the complete webmaster
tutorials reviews reference
ASP
CGI
FrontPage
HTML
Java
JavaScript

Sponsored by El Scripto

Visit the Mortgage Loan Place for Home Loans and also click here to find VA Loans on our site.

Promote your website

home / articles / cgi

Sending Some Content

Just about everyone knows that a CGI script can send an html document. Here's a little bit of code to illustrate how that's done:

#!/usr/local/bin/perl
print "Content-type: text/html\n\n";
print "<html><body><h1>Hi There!</h1></body></html>\n";

The stuff that's printed can be separated into two parts. First, we need to define the content type. This is simply the MIME type for what comes next. That way, the web browser knows what's coming next. There can also be additional headers here, including Date, Size, Expires, Set-Cookie, etc. After two newlines (\n\n), the actual content starts. In this case, it's just another line of text that will be displayed in the web browser with HTML formatting.

To display text without any HTML formatting, use the MIME type text/plain:

print "Content-type: text/plain\n\n";
print "<html><body><h1>Hi There!</h1></body></html>\n";

In this case, you'll actually see the text with all the <html tags> in it. But, what if instead of a simple bunch of text, we wanted to send a jpeg image? Well, that's pretty simple:

print "Content-type: image/jpeg\n\n";
open F, "/path-to-your/jpeg/image.jpg";
while (read F, $r, 16384) { print $r; }
close F;

This bit of code first sends the content (MIME) type and then opens a file. Then it reads 16k bytes from the file until end-of-file is reached -- read returns the actual number of bytes read, so when that value is 0, the while loop will terminate.

Of course, why should we limit ourselves to html and images? We can just easily send any MIME type. The following code will send a .zip file to the user. Depending upon how their browser is configured, they will probably be prompted to save the file to disk.

print "Content-type: application/x-zip-compressed\n\n";
open F, "/path/to/a/zip/file.zip";
while (read F, $r, 16384) { print $r; }
close F;

To find the MIME types for various files, you can just quickly check the settings in your browser. In Netscape 3.0 and before, look on the Options menu under General Preferences...Helpers. In Communicator 4.0, look at the Edit menu, choosePreferences...Navigator...Applications. Or, you can view a comprehensive list available at http://www.isi.edu/in-notes/iana/assignments/media-types/media-types. Also, you can peek into your web server's configuration files. In Apache, this is usually installed at /usr/local/etc/httpd/conf/mime.types.

As you can see, the same code can send a jpeg image, html document, a sound file, zip file or anything else. There's one small problem related to this, however. If a user is prompted to save a file, it will include the name of your script. For example, if the name of your script is pink-floyd.pl and the url is

http://134.71.150.55/cgi-bin/pink-floyd.pl

then you'll see something like this:

Well, that's not exactly the kind of name you want to use for a .zip file.

Instead, we'll have to come up with a way to fool the web browser into thinking that it's looking at a file whose extension ends with .zip. One way to do that would be to rename your script to something like pink-floyd.zip, and then this will work:

http://134.71.150.55/cgi-bin/pink-floyd.zip

But, who really wants to name a perl script ".zip"?

Let's instead redirect the browser to a new url. If the url to your script is

http://134.71.150.55/cgi-bin/led-zeppelin.pl

and you want to save the resulting file as "Kashmir.ZiP", then the following might do that.

#!/usr/local/bin/perl
if (length $ENV{'PATH_INFO'}) {
    # open and send the file
    print "Content-type: application/x-zip-compressed\n\n";
    open F, "/path/to/a/zip/file.zip";
    while (read F, $r, 16384) { print $r; }
    close F;
} else {
    # redirect the browser to the new URL
    print "Location: http://$ENV{'SERVER_NAME'}",
    ":$ENV{'SERVER_PORT'}/$ENV{'SCRIPT_NAME'}/Kashmir.ZiP\n\n";
}
exit 0;

This takes advantage of the fact that a script can be called using the following url syntax:

    /cgi-bin/script_name/path_info

That way, the web browser thinks the file being saved is named "path_info" while the server is smart enough to recognize that the script is named script_name.

In the end, however, there's a really simple way to send out a file. To send a file stored at

    http://your.server.com/path/file.whatever
Issue the following command from your CGI script:

print "Location: http://your.server.com/path/file.whatever\n\n";

That way, the client's web browser will be redirected to the new location from your CGI script. To call a script with the following URL and have it send file.whatever:

    http://your.server.com/cgi-bin/script.pl?file.whatever
Use this script:

#!/usr/local/bin/perl
print "Location: http://$ENV{'SERVER_NAME'}";
print ":$ENV{'SERVER_PORT'}" if $ENV{'SERVER_PORT'}!=80;
print "/$ENV{'QUERY_STRING'}\n\n";

Note that in the last line above, you may need to add a path to the actual file. Let's say that file.whatever is stored in /graphics/pics, then change line 4 above to this:

print "/graphics/pics/$ENV{'QUERY_STRING'}\n\n";

These last few examples that use Location: to redirect the browser assume that you have the MIME type set correctly for the file's extension. You can find more information about that in your web server's documentation.
These scripts have been tested on Apache 1.1.3 and 1.2.4 runing on MkLinux  and Linux 2.x. Your mileage may vary. 

Author: Doug Steinwand
Date: [10/07/97]

More articles about CGI
More articles by Doug Steinwand
Author Biography
Get more website traffic

write for us about us advertise

Copyright 1997, 1998 A Big Lime. All rights reserved.