Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Download .TXT from Perl/CGI Generated HTML

Status
Not open for further replies.

megp

Programmer
Aug 25, 2004
31
US
I have a CGI script that compiles .TXT database info into a table. I'd like to add a link to the page that forces the user to save the .TXT file when they select the link. I'm sure I'm missing something terribly obvious, but forest and trees and all, I'm just not seeing it. Why can't I download my text file?!

Thanks so much,
Meghan

Script currently reads as follows:
Code:
#!/usr/bin/perl

require "cgi-lib.pl";
print &PrintHeader;

if (-e "lock.fil")
{
print &PrintHeader;
print <<"PrintTag";
<html>
<head>
<title>File in Use</title>
<style type="text/css">
h3	{color: red;}
</style>
</head>
<body>
<h3>Error!</h3>
<p>The database is in use.  Please try again later.</p>
</body>
</html>
PrintTag
exit(0);
}

open(LOCK_FILE, ">lock.fil");
open(FILE,"cmaa.txt") || die "Can't find database\n";

@indata = <FILE>;

close(FILE);
close(LOCK_FILE);
unlink("lock.fil");

print <<"PrintTag";
<html>
<head>
<title>Sponsor Logic&reg; CMAA Registration</title>
<style>
<!--
body, td {font-family: verdana, arial, sans-serif; font-size: 8pt;}
-->
</style>

</head>

<body >
<center>
<h3>Club Managers Association of America Registration</h3>

<table border=1 cellspacing=0 cellpadding=2>
<tr>
<td><b>First Name</b></td>
<td><b>Last Name</b></td>
<td><b>Company</b></td>
<td><b>State</b></td>
<td><b>Telephone</b></td>
<td><b>Email</b></td>
<td><b>Password</b></td>
<td><b>Password<br />Confirm</b></td>
</tr>
PrintTag

#Use a foreach loop to process each record in the database
foreach $i (@indata)
{
#Remove hard return from each record
chomp($i);
#Split fields on pipe character
#Assign a variable name to each of the fields
($fname,$lname,$co,$st,$tele,$email,$pwd1,$pwd2) = split(/\|/,$i); 
#Add a new row to the table for each record
print "<tr>";
print "<td>$fname</td>";
print "<td>$lname</td>";
print "<td>$co</td>";
print "<td>$st</td>";
print "<td>$tele</td>";
print "<td><a href=\"mailto:$email\">$email</a></td>";
print "<td>$pwd1</td>";
print "<td>$pwd2</td>";
print "</tr>\n";
#Close the loop
}
print "<tr><td colspan=\"8\"><a href=\"cmaa.txt\">Right Click to Download Database</a></td></tr>";
#Close the table
print "</table>";
print "</center></body></html>";

#End of script
 
the easiest solution is to have a ziped copy of the txt file. But if you want the txt file to download you have to use a header that forces the browser to save the file to disk instead of reading the file. You can't do that with a simple link to the txt file. The CGI module has a parameter for sending files as attachments:

The -attachment parameter can be used to turn the page into an attachment. Instead of displaying the page, some browsers will prompt the user to save it to disk. The value of the argument is the suggested name for the saved file. In order for this to work, you may have to set the -type to "application/octet-stream".

or you can write your own script. I have one I wrote a while back but have not used in a while:

Code:
#!/usr/bin/perl -w
use strict;

my $file = 'cmaa.txt';
my ($name,$ext) = $file =~ /^([^.]+)\.(.*)$/; 
my $path_to_files = '/path/to/files';
my $filesize = -s "$path_to_files/$file";

unless (open(DLFILE, "<$path_to_files/$file")) {
   print "Content-type:text/html\n\n";
   print "Error: Unable to find or open file";
   exit;
}
print "Content-length: $filesize\r\n";
print "Content-Type: application/octet-stream\r\n";
print "Content-Disposition: attachment;filename=\"$file\"\r\n\r\n";
print <DLFILE>;
close (DLFILE);



- Kevin, perl coder unexceptional! [wiggle]
 
Kevin,

Thank you for your quick response. I should have been more specific in my original post: While I'm able to access the .TXT file to populate my table, I am unable to successfully link to it. The .TXT file is a dynamic file, updated with form data via another CGI script (successfully). This script opens the file (successfully), displays the data in a table (successfully), and contains a link at the bottom to enable my client to download the database as a .TXT file (unsuccessfully).

I guess I should have addressed actually being able to download the file before I worried about limiting that download to a "Save as" format, huh?

Meghan
 
Hmm, should have specified. I get a 500 Internal Server Error when I try to open the .TXT file.
 
Probably the reason your href link to the file does not work is because the text file is in the cgi-bin. Normally, the cgi-bin will only allow http access to cgi scripts, not plain documents.

- Kevin, perl coder unexceptional! [wiggle]
 
That's be a 403 - Access Denied though wouldn't it?

500's usually inidcate a problem with the script, check you webserver's error log and see if there's more information there

HTH

Paul
------------------------------------
Spend an hour a week on CPAN, helps cure all known programming ailments ;-)
 
That's be a 403 - Access Denied though wouldn't it?

It might be for some servers. But when I try on my server I get a 500 ISE for a text document in the cgi-bin.



------------------------------------------
- Kevin, perl coder unexceptional! [wiggle]
 
Try creating a small script that responds to the clicked link with this code:


print "Content-Type: text/csv\n";
print "Content-Disposition: attachment; filename=something.csv\n\n";

You can also change the text/csv to text/plain. If that doesn't work for you, let me know, I have something else you can probably try.

 
Ahhhhhh....here is the other thing. Using the CGI module:



print $query->header(-type=>"application/vnd.ms-excel",-attachment=>"path/file.xls",-Content_length=>" -s path/file.xls");


 
I'll have to wait until later in the day to try these out, TorontoJim, but I'm excited that the topic is back on the table. Thank you, PaulTEG and KevinADC, for getting it back out there. I'll let you know what works.

So glad to have folks like you out there to call on for assistance!
Meghan
 
Meghan, we only do it, so people will do it, and remember it meant a lot more before it became IT

just kidding ;-)

Paul
------------------------------------
Spend an hour a week on CPAN, helps cure all known programming ailments ;-)
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top