Реформирование вопроса, потому что
- @optional спросил меня
- было неясно и было связано одно решение HTML:: Mason Четыре простых шага, чтобы сделать Unicode Mason UTF-8 чистым с Apache, mod_perl и DBI, что вызвало недоумение
- оригиналу исполняется 4 года, а между тем (в 2012 году) создается "поэт".
Комментарий: Этот вопрос уже получил "популярный значок вопроса", поэтому, возможно, я не единственный безнадежный человек.:)
К сожалению, демонстрация полного стека проблем приводит к очень длинному вопросу, и это очень важно Mason.
Во-первых, только мнений:)
Я использую HTML:: Mason в возрасте, а теперь пытаюсь использовать Mason2. Poet и Mason являются самыми передовыми системами в CPAN. Не нашел ничего сравнимого, что из коробки позволяет писать так чисто, но очень взломать:)/web-apps, с множеством включенных батарей (ведение журнала, кеширование, управление конфигурацией, собственный PGSI и т.д.)
К сожалению, автор не заботится обо всем остальном, например по умолчанию он основан только на ascii, без любого руководства, faq или советов о: как использовать его с unicode
Теперь факты. Demo. Создайте приложение для поэта:
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:5000https://stackoverflow.com/xls/hello.xlsx, и вы получите:
+----------------------------+
| ÅngstrÖm in the hello.xlsx |
+----------------------------+
download hello.xlsx
Нажав загрузить hello.xlsx, вы получите hello.xlsx
в загрузках.
Вышеупомянутая демонстрация первой проблемы,
например источник источника компонента "под" use utf8;
,
поэтому lc
не понимает символы.
Вторая проблема заключается в следующем: попробуйте [http://0: 5000/xls/hélló.xlsx] или http://0:5000https://stackoverflow.com/xls/h%C3%A9ll%C3%B3.xlsx и вы увидите:
+--------------------------+
| ÅngstrÖm in the hll.xlsx |
+--------------------------+
download hll.xlsx
#note the wrong filename
Конечно, вход (path_info
) не декодируется, script работает с октетами, закодированными utf8, а не с perl-символами.
Итак, указав perl - "источник в utf8", добавив use utf8;
в <%class%>
, результаты
+--------------------------+
| �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 умело позволяет модифицировать его (и Mason's) части,
в $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 году) до сих пор не знаю:( как правильно использовать unicode в Mason2 и по-прежнему не существует никакой документации или помощников об этом.: (
Основные вопросы: - где (какие методы должны быть модифицированы модификаторами метода Moose) и как правильно декодировать входы и где выход (в приложении Poet/Mason.)
- но только текстовые, например.
text/plain
илиtext/html
и такие... - a сделать выше "неожиданно бесплатно" - например, что будет просто работать.;)
Может ли кто-нибудь помочь с реальным кодом - что я должен изменить в приведенном выше?