2009-08-28 3 views
5

Мое веб-приложение работает на Apache mod_perl с использованием CGI :: Application. Я хочу предоставить загрузку сгенерированного файла. В прошлом (до того, как мы использовали mod_perl и CGI :: App), я только размолвил файл csv до STDOUT по мере его создания. Теперь я снимаю для немного более утонченности - создание электронной таблицы Excel с использованием Spreadsheet :: WriteExcel - и я не могу показаться, что вы ее распечатали из дескриптора файла.Как я могу предоставить загрузку временного файла с помощью mod_perl и 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; 
} 

Выходной сигнал - это всего лишь пустой ответ, а предупреждение также пустое.

Метод, который я использую, чтобы написать таблицу в дескриптор файла, довольно прямо из documentation, поэтому я предполагаю, что проблема связана с некоторыми CGI :: App noobery с моей стороны. Предложенные в документации методы для дескрипторов файлов и mod_perl оказались довольно бесплодными.

Я думаю, я должен упомянуть, что я работаю в Windows, и что мое текущее обходное решение - создать файл и предоставить пользователю ссылку на него. Тем не менее это создает больше проблем в отношении очистки каталога и когда это делается, а также проверки подлинности для доступа к сгенерированным файлам.

Предложения? Резкая критика?

ответ

4

Вам не нужно возиться с STDOUT; CGI-App должен правильно обрабатывать вас под капотом. Вам также может понадобиться закрыть дескриптор файла, прежде чем пытаться отправить данные.

Похоже, что вы не устанавливаете правильный тип содержимого для данных Excel. Для чего угодно, кроме text/html, вам нужно установить его вручную. Попробуйте что-то вроде этого:

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; 

}

Вы также можете быть заинтересованы в CGI::Application::Plugin::Stream

+0

Да, я думаю, что закрытие дескриптора файла заставляет его сбрасываться на переменную, чтобы я мог вернуть его. Кроме того, мне пришлось добавить '-attachment => 'filename.xls'' в заголовок, или firefox не мог понять, что делать с файлом. Я рассмотрю CGI :: A :: P :: Stream, но файлы, которые мы создаем, не должны быть достаточно большими, чтобы иметь значение. Спасибо! – wes

3

Вы хотите закрыть книгу. Также закрыть дескриптор:

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

Вместо того чтобы создавать всю таблицу в памяти, вы должны либо записать его в файл и их поток его (с использованием CGI::Application::Plugin::Stream здесь, но вам все равно нужно его очистить после этого, но на самом деле у каждого веб-приложения должен быть временный каталог, который периодически очищается) или распечатывать его при его создании (что означает создание FH STDIN вместо этого это может быть сложнее в mod_perl или может будь не).

И тогда не забудьте закрыть свою книгу, когда это будет сделано.

 Смежные вопросы

  • Нет связанных вопросов^_^