2009-08-28 13 views
5

Mi aplicación web se ejecuta en Apache mod_perl usando CGI :: Aplicación. Deseo proporcionar una descarga de un archivo generado. En el pasado (antes de que usáramos mod_perl y CGI :: App) acabo de poner en cola un archivo csv al STDOUT mientras se generaba. Ahora estoy buscando un poco más de refinamiento, creando una hoja de cálculo de Excel usando Spreadsheet :: WriteExcel, y no puedo imprimirlo desde el manejador del archivo.¿Cómo puedo proporcionar una descarga temporal de archivos usando mod_perl y CGI :: Application?

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; 
} 

la salida es sólo una respuesta en blanco, y la advierten está en blanco también.

El método que estoy usando para escribir la hoja de cálculo en un manejador de archivos es bastante directo del documentation, así que supongo que el problema se debe a algo de la noober CGI :: App de mi parte. Los métodos sugeridos por la documentación para filehandles y mod_perl también resultaron bastante infructuosos.

Supongo que debería mencionar que me estoy ejecutando en Windows, y que mi solución actual es crear un archivo y proporcionarle un enlace al usuario. Eso plantea más problemas, sin embargo, en cuanto a la limpieza del directorio y cuándo hacerlo, y también la autenticación para acceder a los archivos generados.

Sugerencias? Mordaz crítica?

Respuesta

4

No debería ser necesario meterse con STDOUT; CGI-App debería manejarlo adecuadamente para usted bajo el capó. También es posible que deba cerrar el identificador de archivo antes de intentar enviar los datos.

Parece que no está configurando un tipo de contenido adecuado para los datos de Excel. Para cualquier cosa que no sea text/html, tendrá que configurarlo manualmente. Intentar algo como esto:

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; 

}

Usted también podría estar interesado en CGI::Application::Plugin::Stream

+0

Sí, supongo que al cerrar la maneta de archivo se fuerza a nivelar la variable para que pueda devolverla. Además, tuve que agregar '-attachment => 'filename.xls'' al encabezado o firefox no pudo entender qué hacer con el archivo. Buscaré en CGI :: A :: P :: Stream, pero los archivos que estamos creando no deberían ser lo suficientemente importantes como para importar. Gracias! – wes

3

Quiere cerrar el libro de trabajo. También cerrar el gestor de archivo:

warn "length 1=".length($str); 
$workbook->close(); 
close($fh) or die "error on close: $!"; 
warn "length 2=".length($str); 

length 1=0 at wx.pl line 16. 
length 2=5632 at wx.pl line 19. 
4

En vez de crear toda la hoja de cálculo en la memoria, usted debe o escribirlo en un archivo y los fluirlo cuando termine (usar CGI::Application::Plugin::Stream ayuda aquí, pero aún deberá limpiarlo después, pero en realidad cada aplicación web debe tener un directorio temporal que periódicamente se limpia) o imprimirlo mientras lo crea (lo que significa que debe hacer el FH STDIN en su lugar, que podría ser más complicado bajo mod_perl o puede no seas).

Y luego recuerde cerrar su libro cuando esté listo.

Cuestiones relacionadas