【发布时间】:2011-08-17 01:07:27
【问题描述】:
重新表述问题,因为
- @可选asked me
- 不清楚并链接了一个基于HTML::Mason 的解决方案Four easy steps to make Mason UTF-8 Unicode clean with Apache, mod_perl, and DBI ,是什么导致了混淆
- 原作4岁,同时(2012年)创作了“诗人”
评论:这个问题已经获得了“热门问题徽章”,所以可能我不是唯一一个绝望的人。 :)
不幸的是,演示完整问题堆栈会导致一个很长的问题,而且它非常具体Mason。
首先,只有意见的部分:)
我使用 HTML::Mason 已经很久了,现在尝试使用 Mason2。 Poet 和 Mason 是 CPAN 中最先进的框架。 找不到任何可比的东西,开箱即用的东西允许写得如此干净/但非常容易破解:)/网络应用程序, 包括许多电池(日志记录、缓存、配置管理、基于原生 PGSI 等...)
不幸的是,作者并不关心这个词的其余部分, 例如默认情况下,它仅基于 ascii, 没有任何手册、常见问题解答或关于以下方面的建议:如何将其与 unicode 一起使用
现在是事实。演示。创建一个诗人应用程序:
poet new my #the "my" directory is the $poet_root
mkdir -p my/comps/xls
cd my/comps/xls
并在dhandler.mc 中添加以下内容(将演示这两个基本问题)
<%class>
has 'dwl';
use Excel::Writer::XLSX;
</%class>
<%init>
my $file = $m->path_info;
$file =~ s/[^\w\.]//g;
my $cell = lc join ' ', "ÅNGSTRÖM", "in the", $file;
if( $.dwl ) {
#create xlsx in the memory
my $excel;
open my $fh, '>', \$excel or die "Failed open scalar: $!";
my $workbook = Excel::Writer::XLSX->new( $excel );
my $worksheet = $workbook->add_worksheet();
$worksheet->write(0, 0, $cell);
$workbook->close();
#poet/mason output
$m->clear_buffer;
$m->res->content_type("application/vnd.ms-excel");
$m->print($excel);
$m->abort();
}
</%init>
<table border=1>
<tr><td><% $cell %></td></tr>
</table>
<a href="?dwl=yes">download <% $file %></a>
并运行应用程序
../bin/run.pl
转到http://0:5000/xls/hello.xlsx,您将获得:
+----------------------------+
| ÅngstrÖm in the hello.xlsx |
+----------------------------+
download hello.xlsx
点击download hello.xlsx,您将在下载中获得hello.xlsx。
上面演示了第一个问题,
例如组件的源不在use utf8;“下”,
所以lc 不理解字符。
第二个问题如下,试试 [http://0:5000/xls/hélló.xlsx],或 http://0:5000/xls/h%C3%A9ll%C3%B3.xlsx 你会看到:
+--------------------------+
| ÅngstrÖm in the hll.xlsx |
+--------------------------+
download hll.xlsx
#note the wrong filename
当然,输入(path_info)没有被解码,脚本使用 utf8 编码的八位字节而不是 perl 字符。
所以,通过将use utf8; 添加到<%class%> 中,告诉 perl -“源代码在 utf8 中”,结果
+--------------------------+
| �ngstr�m in the hll.xlsx |
+--------------------------+
download hll.xlsx
添加use feature 'unicode_strings'(或use 5.014;)更糟糕:
+----------------------------+
| �ngstr�m in the h�ll�.xlsx |
+----------------------------+
download h�ll�.xlsx
当然,源现在包含宽字符,输出时需要Encode::encode_utf8。
可以尝试使用以下过滤器:
<%filter uencode><% Encode::encode_utf8($yield->()) %></%filter>
并过滤整个输出:
% $.uencode {{
<table border=1>
<tr><td><% $cell %></td></tr>
</table>
<a href="?dwl=yes">download <% $file %></a>
% }}
但这只是部分帮助,因为需要注意<%init%> 或<%perl%> 块中的编码。
在许多地方对 perl 代码内部进行编码/解码(阅读:不是在边界)会导致代码冗长。
编码/解码应该清楚地在某处完成 Poet/Mason 边界——当然,Plack 在字节级别上运行。
部分解决方案。
很高兴,Poet 巧妙地允许修改它(和梅森)的部分,所以,
在$poet_root/lib/My/Mason 中,您可以将Compilation.pm 修改为:
override 'output_class_header' => sub {
return join("\n",
super(), qq(
use 5.014;
use utf8;
use Encode;
)
);
};
什么会将所需的序言插入到每个 Mason 组件中。 (不要忘记触摸每个组件,或者干脆从$poet_root/data/obj 中删除已编译的对象。
您也可以尝试在边界处理请求/响应,
通过将$poet_root/lib/My/Mason/Request.pm 编辑为:
#found this code somewhere on the net
use Encode;
override 'run' => sub {
my($self, $path, $args) = @_;
#decode values - but still missing the "keys" decode
foreach my $k (keys %$args) {
$args->set($k, decode_utf8($args->get($k)));
}
my $result = super();
#encode the output - BUT THIS BREAKS the inline XLS
$result->output( encode_utf8($result->output()) );
return $result;
};
对所有内容进行编码是一个错误的策略,它会中断,例如XLS。
所以,4 年后(我在 2011 年问了原始问题)仍然不知道 :( 如何在 Mason2 应用程序中正确使用 unicode,但仍然不存在有关它的文档或帮助者。:(
主要问题是: - 在哪里(Moose 的方法修饰符应该修改哪些方法)以及如何正确解码输入以及输出在哪里(在 Poet/Mason 应用程序中。)
- 但只有文本,例如
text/plain或text/html等等... - 执行上述“无惊喜” - 例如。什么会简单有效。 ;)
有人可以帮忙提供真实的代码吗?我应该在上面修改什么?
【问题讨论】:
标签: perl utf-8 moose mason plack