Search code examples
perlapachedownloadmod-perlcgi-application

How can I provide a temp file download using mod_perl and CGI::Application?


My web app runs on Apache mod_perl using CGI::Application. I want to provide a download of a generated file. In the past (before we were using mod_perl and CGI::App) I just spooled out a csv file to STDOUT as it was generated. Now I'm shooting for a little more refinement - creating an Excel spreadsheet using Spreadsheet::WriteExcel - and I can't seem it to get to print it out from the file handle.

sub export_list {
  my $self = shift;

  binmode(STDOUT);
  my $str;
  open my $fh, '>', \$str;
  my $workbook = Spreadsheet::WriteExcel->new($fh);
  my $worksheet = $workbook->add_worksheet();

  $worksheet->write_col(0,0, ['some','data','here']);
  warn $str;
  return $str;
}

The output is just a blank response, and the warn is blank as well.

The method I'm using to write the spreadsheet to a filehandle is pretty much straight out of the documentation, so I assume the problem is due to some CGI::App noobery on my part. The documentation's suggested methods for filehandles and mod_perl proved pretty fruitless as well.

I guess I should mention I'm running on Windows, and that my current workaround is to create a file and provide the user with a link to it. That poses more problems, however, in regards to clearing out the directory and when to do so, and also authentication for access to the generated files.

Suggestions? Scathing criticism?


Solution

  • You shouldn't need to mess with STDOUT; CGI-App should handle that properly for you under the hood. You'll also may need to close the filehandle before you try to send the data.

    It looks like you're not setting a proper content type for the Excel data, though. For anything other than text/html, you'll need to set it manually. Try something like this:

    sub export_list {
        my $self = shift;
    
        my $str;
        open my $fh, '>', \$str or die "Can't open to var: $!";
        my $workbook = Spreadsheet::WriteExcel->new($fh);
        my $worksheet = $workbook->add_worksheet();
    
        $worksheet->write_col(0,0, ['some','data','here']);
    
        $workbook->close;
        close $fh;
    
        warn $str;
    
        $self->header_add( -type => 'application/vnd.ms-excel' );
        return $str;
    

    }

    You may also be interested in CGI::Application::Plugin::Stream