Как я могу обеспечить загрузку временного файла, используя mod_perl и CGI :: Application? - PullRequest
5 голосов
/ 29 августа 2009

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

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

Вывод является просто пустым ответом, а предупреждение также пустым.

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

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

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

Ответы [ 3 ]

4 голосов
/ 29 августа 2009

Вам не нужно связываться с 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

4 голосов
/ 29 августа 2009

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

А затем не забудьте закрыть свою книгу, когда она будет завершена.

3 голосов
/ 29 августа 2009

Вы хотите закрыть рабочую книгу. Также закройте дескриптор файла:

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.
...