вторник, 15 мая 2012 г.

Mojolicious::Plugin::RenderFile для отдачи файлов

Стояла задача дать пользователю возможность скачать файл. Покопавшись в документации, я нашел 2 варианта - хелперы "render_data" и "render_static". Оба варианта мне не подошли. 
"render_data" - принимает строку, а я не хотел вычитывать весь файл в память.
"render_static" - отдает файлы с "public" директории.

render_file 
Интернет предложил различные варианты решения проблемы, но какого-то удобного я не нашел, решил написать свой хелпер. Хелпер должен был уметь отдавать файл по абсолютному пути с любой папки без вычитывания файла в память, и чтобы браузер предлагал пользователю файл сохранить, а не пытался рендерить. Так появился "render_file". Используется он так:
# Provide any file name
$self->render_file(
    filepath => '/tmp/files/file.pdf',  
    filename => 'report.pdf'
);

Реализация достаточно проста:
$app->helper('render_file' => sub {
my $c = shift;
my %args = @_;
my $filepath = $args{filepath};
unless ( -f $filepath && -r $filepath ) {
$c->app->log->error("Cannot read file [$filepath]. error [$!]");
return;
}
my $filename = $args{filename} || fileparse($filepath);
my $status = $args{status} || 200;
my $headers = Mojo::Headers->new();
$headers->add( 'Content-Type', 'application/x-download;name=' . $filename );
$headers->add( 'Content-Disposition', 'attachment;filename=' . $filename );
$c->res->content->headers($headers);
# Stream content directly from file
$c->res->content->asset( Mojo::Asset::File->new( path => $filepath ) );
return $c->rendered($status);
} );
view raw render_file.pl hosted with ❤ by GitHub
Добавил тесты и залил на CPAN в виде плагина Mojolicious::Plugin::RenderFile

8 коммент.:

Andriy Radyk комментирует...

Может подскажешь, как организовать динамический вывод данных в csv подобно json в Mojolicious

koorchik комментирует...

Не понял вопроса. Вывод в csv файл? В чем основная задача?

Andriy Radyk комментирует...

Основная задача:
есть данные, нужно сфомировать csv и вывести csv с нужным content type для загрузки из браузера.

В данном случае можно сгенерировать файл и отдать его твоим плагином. Но если отдавать не файл, а сгенерированые данные?

Как проще всего это сделать используя Mojolicious?

koorchik комментирует...

Можно использовать "data" вместо "filеpath" - $self->render_file('data'=>$csv_data, 'filename'=>'some_file.csv');

Andriy Radyk комментирует...

Спасибо! Идеально.

Анонимный комментирует...

Спасибо!
Как раз то что искал :)

good code комментирует...

Пользовал его =) Приятно удивлен, что это ты! Спасибо!

SHok комментирует...

Как раз то что нужно было, большое спасибо!

Отправить комментарий

Не забудьте добавить себя в постоянные читатели и включить уведомления о новых комментариях, либо воспользуйтесь RSS каналом ;)