Как я могу обеспечить загрузку временного файла, используя mod_perl и CGI::Application?
Мое веб-приложение работает на 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 ответа
Вам не нужно связываться с 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
Вместо того, чтобы создавать всю электронную таблицу в памяти, вы должны либо записать ее в файл, а затем завершить ее потоковую передачу (используя http://search.cpan.org/perldoc?CGI::Application::Plugin::Stream, но вам все равно придется впоследствии ее очистить)., но на самом деле каждое веб-приложение должно иметь временный каталог, который периодически очищается) или распечатывать его по мере его создания (что означает создание FH STDIN
вместо этого, что может быть сложнее под mod_perl или, возможно, нет).
И затем не забудьте закрыть свою рабочую книгу, когда это будет сделано.
Вы хотите закрыть рабочую книгу. Также закройте дескриптор файла:
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.