Perl: как отдать Excel-файл из CGI-сценария

Date March 21st, 2014 Author Vitaly Agapov

Our purpose for living is to find that perfection and show it forth. // Смысл жизни в том, чтобы достигнуть совершенства и рассказать об этом другим.

Ричард Бах «Чайка по имени Джонатан Ливингстон»

perl-camel-xls

Новая микрозаметка из мира Perl, растерявшего в последнее время былую популярность, но не мой интерес и нежные чувства. На этот раз о том, как сгенерировать XLS-файл по запросу в CGI-сценарий о отдать его пользователю в виде аттачмента.

Сам процесс создания файла ложится на плечи модуля Spreadsheet::WriteExcel, о котором всю подробную документацию можно прочитать на CPAN.

Вот, собственно, сам сниппет с комментариями.





#!/usr/bin/perl
use Spreadsheet::WriteExcel;
use Encode;
use CGI;

my $cgi = new CGI;

# Добавляем заголовки Content-Type, Content-Disposition и Expires
print $cgi->header(
        -type    => 'application/xls',
        -attachment => 'alert.xls',
        -expires => '-1d'
);

# Будем писать в бинарный поток
binmode(STDOUT);
my $workbook = Spreadsheet::WriteExcel->new(\*STDOUT);

# Создаём новую страницу
my $worksheet = $workbook->add_worksheet('page1');

# Пишем значения, в общем симулируем полезные действия

my ($row, $col);
$worksheet->write($row, $col++, "Hello");
$worksheet->write($row, $col, "World");
$row++;
$col=0;
$worksheet->write($row, $col++, decode_utf8("Привет"));
$worksheet->write($row, $col, decode_utf8("Мир"));

# Закрываем файл
$workbook->close();

В общем-то всё. Для полноты картины, правда, ещё можно посмотреть, как отдать уже готовый файл. Или рассмотреть ситуацию, когда необходимо, чтобы файл не только отдавался пользователю, но и сохранялся на сервере для будущего использования. 

Во-первых, для этого понадобится заменить в конструкторе new() хэндлер на имя файла:

my $workbook = Spreadsheet::WriteExcel->new($filename);

Во-вторых, после $workbook->close() добавить вывод этого файла:

use constant BUFFER_SIZE => 4096;
open( FILE, '<', $filename ) or die("open failed: $!");
binmode(FILE);
binmode(STDOUT);
my $buf;
while ( read(FILE, $buf, BUFFER_SIZE) ) { 
	print $buf; 
}
close FILE;

Tags:
Category: Perl | No comments »

Comments

Leave a comment

 Comment Form