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

Hey, most knowledgeable Monks!

I've been searching this problem to no avail. My foo is weak.

I've got data displayed in a CGI script which I need to modify as a CSV and allow the user to save locally preferably through the browser's "Save as" dialog. Formatting the data as rows of comma-delimited values is trivial, but I'm running into a wall on how to save the data locally.

Do you have any suggestions?

Thanks!

Replies are listed 'Best First'.
Re: saving data locally in CGI script?
by ikegami (Patriarch) on Jan 22, 2010 at 20:21 UTC
    use strict; use warnings; use CGI; my $cgi = CGI->new(); sub handle_error { print $cgi->header( -status => 500, -type => 'text/html', ); print ...; exit(0); } open(my $fh, '<', 'foo.csv') or handle error(...); print $cgi->header( # application/octet-stream might work better -type => 'text/csv', -attachment => 'foo.csv', ); print while <$fh>;

    Of course, you can base the name of the CSV on a CGI parameter or on a session field. Or you can generate it on the fly instead of reading it form disk.

      Thanks! Your idea made this even more compact:

      my $cgi = CGI->new(); my $s = "Hi, Mom!\n"; print $cgi->header(-type => 'text/csv', -attachment => 'filename.c +sv', -Content-length => length($s)); print $s;

      Is it possible to generate the standard file-open dialog such that the filename can be changed?

        To pick the name of the file to which to save? Your browser should do that already.

Re: saving data locally in CGI script?
by Corion (Patriarch) on Jan 22, 2010 at 20:15 UTC

    If you mean that you want the browser to prompt the user where to download your CSV file, that's a matter of sending the proper HTTP headers. In your case, you need to send the appropriate Content-Disposition header:

    print "Content-Disposition: attachment; filename=test.csv\r\n\r\n";

      Thanks! The following appears to work:

      my $s = "Hi, Mom!\n"; # print "Content-disposition: inline; filename=docket.csv\n"; print "Content-disposition: attachment; filename=docket.csv\n"; print "Content-length: " . length($s) . "\n"; print "Content-type: application/octet-stream\n\n"; print $s;
      Specifying inline or attachment appears to work in the same manner.

      Is there a way to display the standard file-open dialog such that the user can rename the file as desired?

      Thanks, again!

Re: saving data locally in CGI script?
by Utilitarian (Vicar) on Jan 22, 2010 at 20:16 UTC
    You need to send a header in response to the submit which defines your content as a csv text file. You can use the following
    Content-type:text/csv\n\n

    print "Good ",qw(night morning afternoon evening)[(localtime)[2]/6]," fellow monks."