# ----------------------------------------------------------------------------- # Tripletail::Filter::CSV - CSV出力フィルタ # ----------------------------------------------------------------------------- package Tripletail::Filter::CSV; use strict; use warnings; use Tripletail; require Tripletail::Filter; our @ISA = qw(Tripletail::Filter); # オプション一覧: # * charset => 出力の文字コード。(UTF-8から変換される) # Encode.pmが利用可能なら利用する。(UniJP一部互換エンコード名、sjis絵文字使用不可) # デフォルト: Shift_JIS # * contenttype => デフォルト: text/csv; charset=(CHARSET) # * filename => 指定されると、そのファイル名で Content-Disposition を出力する。 1; sub _new { my $class = shift; my $this = $class->SUPER::_new(@_); # Contentが1バイトでも出力されたかどうか $this->{content_printed} = undef; # デフォルト値を埋める。 my $defaults = [ [linebreak => "\r\n"], [charset => 'Shift_JIS'], [contenttype => sub { # 動的に決まるのでCODE Refを渡す。引数は取らない。 require Tripletail::CharConv; my $ctype; $ctype = sprintf 'text/csv; charset=%s', $this->{option}{charset}; if(defined($this->{option}{filename})) { $ctype .= qq{; name="$this->{option}{filename}"}; } $ctype; }], ]; $this->_fill_option_defaults($defaults); # オプションのチェック my $check = { linebreak => [qw(defined no_empty scalar)], charset => [qw(defined no_empty scalar)], contenttype => [qw(defined no_empty scalar)], filename => [qw(no_empty scalar)], }; $this->_check_options($check); $this->setHeader('Content-Type' => $this->{option}{contenttype}); if(defined($this->{option}{filename})) { my $filename = $this->{option}{filename}; $filename = $TL->charconv($filename, 'UTF-8' => $this->{option}{charset}); $this->setHeader('Content-Disposition' => qq{attachment; filename="$filename"}); } $this; } sub print { my $this = shift; my $data = shift; my $output = $this->_flush_header; if (ref($data)) { if (ref($data) eq 'ARRAY') { $data = $TL->getCsv->makeCsv($data) . $this->{option}{linebreak}; } else { die __PACKAGE__."#print: arg[1] is neither a SCALAR nor an ARRAY Ref. [$data] (第1引数がスカラでも配列のリファレンスでもありません)\n"; } } $output .= $TL->charconv($data, 'utf8' => $this->{option}{charset}); if (length($output)) { $this->{content_printed} = 1; } $output; } sub flush { my $this = shift; if(!$this->{content_printed}) { die __PACKAGE__."#flush: no contents has been printed during this request. (リクエスト処理で何もprintされていません)\n"; } ''; } sub reset { my $this = shift; $this->SUPER::reset; $this->{content_printed} = undef; $this->setHeader('Content-Type' => $this->{option}{contenttype}); if(defined($this->{option}{filename})) { my $filename = $this->{option}{filename}; $filename = $TL->charconv($filename, 'UTF-8' => $this->{option}{charset}); $this->setHeader('Content-Disposition' => qq{attachment; filename="$filename"}); } $this; } __END__ =encoding utf-8 =for stopwords CSV YMIRLINK addHeader contenttype linebreak setHeader =head1 NAME Tripletail::Filter::CSV - CSV 出力フィルタ =head1 SYNOPSIS $TL->setContentFilter( 'Tripletail::Filter::CSV', charset => 'UTF-8', filename => 'foo.csv', ); $TL->print('aaa,"b,b,b",ccc,ddd' . "\r\n"); $TL->print(['aaa', 'b,b,b', 'ccc', 'ddd']); =head1 DESCRIPTION CSV の出力を支援する。 ファイル名の指定で Content-Disposition を出力可能。 また、このフィルタの使用時には、L<< $TL->print|Tripletail/"print" >> に文字列の配列を渡す事も出来る。配列が渡された場合は、各要素を 必要に応じて "" で囲み、カンマで繋げ、改行コードを付けて出力する。 文字列を渡す場合は、改行コードは付与されないことに注意。 =head2 フィルタパラメータ =over 4 =item charset 出力文字コードを指定する。省略可能。 使用可能なコードは次の通り。 UTF-8,Shift_JIS,EUC-JP,ISO-2022-JP デフォルトはShitf_JIS。 =item contenttype $TL->setContentFilter('Tripletail::Filter::CSV', contenttype => 'text/html; charset=sjis'); C を指定する。省略可能。 デフォルトはtext/csv; charset=(charasetで指定された文字コード)。 =item linebreak 配列が渡されたときに、どのような改行コードを利用するかを指定する。省略可能。 デフォルトは "\r\n"。 =item filename ヘッダで出力するファイル名を指定する。省略可能。 指定した場合、次のようなヘッダが出力される。 Content-Type: text/csv; charset=Shift_JIS; name="foo.csv" Content-Disposition: attachment; filename="foo.csv" 指定しない場合は、次のようなヘッダが出力される。 Content-Type: text/csv; charset=Shift_JIS =back =head2 METHODS =over 4 =item setHeader $filter->setHeader($key => $value) 他の出力の前に実行する必要がある。 同じヘッダを既に出力しようとしていれば、そのヘッダの代わりに指定したヘッダを出力する。(上書きされる) =item addHeader $filter->addHeader($key => $value) 他の出力の前に実行する必要がある。 同じヘッダを既に出力しようとしていれば、そのヘッダに加えて指定したヘッダを出力する。(追加される) =item flush L参照 =item print L参照 =item reset L参照 =back =head1 SEE ALSO =over 4 =item L =item L =item L =back =head1 AUTHOR INFORMATION =over 4 Copyright 2006 YMIRLINK Inc. This framework is free software; you can redistribute it and/or modify it under the same terms as Perl itself このフレームワークはフリーソフトウェアです。あなたは Perl と同じライセンスの 元で再配布及び変更を行うことが出来ます。 Address bug reports and comments to: tl@tripletail.jp HP : http://tripletail.jp/ =back =cut