Переформулировка вопроса, потому что
Комментарий: этот вопрос уже получил «знак популярного вопроса», так что, вероятно, я не единственный безнадежный человек.:)
К сожалению, демонстрация проблемного стека full приводит к очень длинному вопросу, который очень специфичен Mason .
First, часть только для мнений:)
Я использую HTML :: Mason уже много лет, и сейчас пытаюсь использовать Mason2. Poet и Mason - самые передовые фреймворки в CPAN.Ничего не сравнимого с тем, что «из коробки» позволяет писать такие чистые / но очень хакерские:) / веб-приложения со многими включенными батареями (ведение журналов, кеширование, управление конфигурациями, на основе PGSI и т. Д.) *
К сожалению, автору нет дела до остального слова, например, по умолчанию оно основано только на ascii, без любого руководства, часто задаваемых вопросов или советов по поводу: how чтобы использовать его с 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: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.
Итак, говоря 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 во многих местах, ( чтение: не на границах ) приводит к неправильному коду.
Кодирование / декодирование должно бытьчетко сделано где-то на Поэт / Мейсон границы - конечно, Plack работает на уровне байтов.
Частичное решение.
К счастью, Поэт умело позволяет изменять его (и Мейсон) части, поэтому в $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
to:
#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 и до сих пор не существует никакой документации или помощников по этому поводу.: (
Основные вопросы: - где (какие методы должны быть модифицированы модификаторами методов Муса) и как правильно декодировать входные данные и где выходные данные (в приложении Poet / Mason.)
- , но только текстовые, например
text/plain
или text/html
и т. П. - a делают вышеупомянутое "без сюрпризов" - например, то, что будет просто работать.;)
Может кто-нибудь помочь с реальным кодом - что я должен изменить в приведенном выше?