日本語ファイル名をIEでダウンロードするときの文字化け対策

日本語ファイル名をIEでダウンロードするときの文字化け対策

by Katsunori Mizuno -
Number of replies: 16

Moodle 1.8+ を CentOS 4.5 と 5.0 で使っています。

Yoshidaさんや奥村先生の日本語ファイル名操作用のパッチを当てた状態で、IE6sp2, IE7 で日本語ファイル名のファイルをダウンロードすると、「予」「表」のように「¥(0x5C)」を含むファイル名が文字化けしてしまいました。

「予 (0x975c)」→「誉 (0x975f)」 「表 (0x955c)」→「廟 (0x955f)」

パッチの以下の部分を変更したところ、上記の文字化けはなくなりました。

変更前:
  if (strstr($ua, "MSIE") && !strstr($ua, 'Opera')) {
      $filename = mb_convert_encoding($filename, "SJIS-WIN", "UTF-8");
変更後:
 if (strstr($ua, "MSIE") && !strstr($ua, 'Opera')) {

UTF-8のファイル名を urlencode すれば IE では文字化けしないという記述を見つけたので、上記のように変更してみました。

「平成19年度行事予定表.pdf」というファイルをIEで、アップロード、ダウンロードが正常に出来ています。

何か副作用があるかもしれませんので、他の環境でも試して頂けないでしょうか。

Average of ratings: -
In reply to Katsunori Mizuno

Re: 日本語ファイル名をIEでダウンロードするときの文字化け対策

by Haruhiko Okumura -
ありがとうございます!
私自身はIEを使っていないので,このようなフィードバックがいただけるとたいへん助かります。今日の夜にでもこっそり直してみて,苦情が増えるか減るか試してみます。
In reply to Haruhiko Okumura

Re: 日本語ファイル名をIEでダウンロードするときの文字化け対策

by Katsunori Mizuno -

その後、Googleで検索して以下のことが分かりました。

文字化けするのは、ShiftJIS の2バイト目が「5C」「7C」になっている場合、「5F」になってしまうようで、IE7のバグとしてマイクロソフトの技術情報にも載っていました。

Internet Explorer 7 からファイル名に日本語を含むファイルをダウンロードすると、ファイル名の一部が変更されることがある
http://support.microsoft.com/kb/930938/ja

ファイルをダウンロードする ASP.NET Web ページで日本語ファイル名が文字化けする
http://support.microsoft.com/kb/436616/

urlencode()で回避する方法は、やはり万能ではないようで、長い日本語ファイル名の場合、文字化けやファイル名が短くなったりするとのことです。

下記のサイトでは、問題になる文字のみ urlencode() することで、問題を発生しにくくする方法が紹介されていました。

IE7でダウンロードをするとファイル名の日本語部分が変に化ける
http://shain.tomocreative.net/2007/02/ie7.html

マイクロソフトからパッチが提供されれば、今までどおり ShiftJIS に変換するのがよさそうですが、それまでは、urlencode() を使ってごまかすしかないようです。

Average of ratings: お役立ち度: ★★★★★☆☆ (1)
In reply to Katsunori Mizuno

Re: 日本語ファイル名をIEでダウンロードするときの文字化け対策

by Haruhiko Okumura -
そういえば,5C 7Cのバグについては聞いたことがありましたが,忘れていました。まだ直っていなかったのですね。
urlencodeにも問題があるんですね。ちょっと迷っています。
In reply to Haruhiko Okumura

Re: 日本語ファイル名をIEでダウンロードするときの文字化け対策

by Tatsuya Shirai -
半角空白を含むファイルをFirefoxでダウンロードしようとすると,半角空白以降が消えてしまうという問題に遭遇しました.例えば,"情報班の常識 (Wiki).zip"が,"情報班の常識"というファイル名でダウンロードされます.(”常識”と”(”の間に半角の空白あり)

この問題の原因箇所は,lib/filelib.php中のsend_file()にあり,295行目あたりから始まるヘッダー情報の送出に関わっているようですね.丁度,別件(Wikiのエクスポート)で悩んでいた問題と偶然にも一致します).
if ($forcedownload) {
@header('Content-Disposition: attachment; filename='.$filename);
} else {
@header('Content-Disposition: inline; filename='.$filename);
}
ファイルのダウンロード時は$forcedownloadがゼロでしたので,attachmentではなく,inlineの側のheader()が関わっています.

当初は,
if ($forcedownload) {
@header('Content-Disposition: attachment; filename='.$filename);
} else {
// @header('Content-Disposition: inline; filename='.$filename);
@header('Content-Disposition: inline; filename*=iso-2022-jp\'ja\''.rawurlencode($filename));
}
とすることで無事にIE6でもFirefoxでもダウンロードできるようになりました.さらに何の気もなしに,
if ($forcedownload) {
@header('Content-Disposition: attachment; filename='.$filename);
} else {
// @header('Content-Disposition: inline; filename='.$filename);
// @header('Content-Disposition: inline; filename*=iso-2022-jp\'ja\''.rawurlencode($filename));
}
のように完全にコメントアウトしても正しくダウンロードできることを発見.上の方の行のコメントを外すと化けますので,単に$filnameを与えただけでは誤動作するので,いっそのこと省略してしまった方がマシだ,ということなのでしょうか.
(この解釈は奥村先生のページを参考にしました)

filename*=iso-2022-jpといった表現は古いブラウザーでも対応しているのか,Content-Dispositionを省略しても正しいファイル名でダウンロードできるのか,という検証は多くのブラウザとそのバージョンをチェックしないといけないのかも知れません.IE6SP2とFIrefox2では大丈夫らしい,という報告です.

ちなみに,files.phpの最後の方に奥村先生が追加された,
$filename = str_replace('#', '%23', $filename);
ですが,上記iso-2022といった指定やContent-Dispositionを省略した場合においては,逆に副作用が出ました."情報#班の常識 (Wiki).zip"という変な名前にリネームしてダウンロードをしてみたところ,"情報%20班の常識 (Wiki).zip"となりました.一部だけurlencode()が有効な場合と無効な場合はどこにあるのか分かりませんが,私の環境(Firefox2.0.0.5)では,str_replace()は不要のようです.

In reply to Tatsuya Shirai

Re: 日本語ファイル名をIEでダウンロードするときの文字化け対策

by Haruhiko Okumura -
三重大学版では

@header('Content-Disposition: attachment; filename="'.$filename.'"'); // okumura: added ""

のように引用符を増やしてありますが,これでうまくいっているのか自信ありません。
In reply to Haruhiko Okumura

Re: 日本語ファイル名をIEでダウンロードするときの文字化け対策

by Tatsuya Shirai -
奥村先生のページを見た際に,なるほど,と思ってダブルクォートによって囲む方法も試したののですが,その時は駄目でした.でも,いまやり直してみたらうまく行きました.isoほにゃららよりも分かり易いですね.”で囲む方式で行きましょう.ありがとうございます.


ただ,#記号の問題は残ります.
こちらはFirefox2.0.0.5ですと#を%23に置き換えると,そのまま%23を含むファイル名でダウンロードされてしまいますので,IEの場合のみ#を%23に置き換える方が良いかも知れません.(ブラウザのバージョンによるのかも知れません)

file.phpの例の箇所ですが,
if (strstr($ua, "MSIE") && !strstr($ua, 'Opera')) {
$filename = mb_convert_encoding($filename, "CP932", "UTF-8");
$filename = str_replace('#', '%23', $filename);
} else if (strstr($ua, "Safari")) {
$filename = "";
}
send_file($pathname, $filename, $lifetime, $CFG->filteruploadedfiles, false, $forcedownload);
のように,MSIEの場合の処理の方に移動させていまは運用しています.


前の方の書き込みで#が%20になる,と書いてあるのは単なるミスです.紛らわしくしてしまって申し訳ありません.
In reply to Tatsuya Shirai

Re: 日本語ファイル名をIEでダウンロードするときの文字化け対策

by Haruhiko Okumura -
なるほど。そういえば # が消えるというクレームがあったのはIEだったような。こちらもそのようにします。
In reply to Tatsuya Shirai

Re: 日本語ファイル名をIEでダウンロードするときの文字化け対策

by Haruhiko Okumura -
あと,日本語ファイル名の問題として,Moodleの中でZIP化してダウンロードしてWindowsで展開すると文字化けする(Macなら大丈夫)という問題があるようです。白井先生のパッチでは対応されていましたでしょうか。
In reply to Haruhiko Okumura

Re: 日本語ファイル名をIEでダウンロードするときの文字化け対策

by Tatsuya Shirai -
ZIP化するファイルのリストを現在選択しているファイルシステムの文字コードに変換してからZIP化するように改造しましたので大丈夫でしょう.moodleのサーバがS-JIS(つまりWindowsサーバ)ならば,ZIP書庫内のファイルリストはS-JISコードで格納されます.

余計かな,とも思ったのですがオマケで付けた機能もあります.
もしS-JIS以外の文字コードをファイルシステムの文字コードとして選択している場合,ファイルリストは現在選択している文字コード(例えばUTF-8)のままでZIP化されますので,Windows環境で展開時にフォルダ名/ファイル名が文字化けします.そこで,手動でZIP化する場合だけは,添付した画像のように「zip書庫を作成する」の下に「SJISでzip書庫作成」のメニューが現れるようにしましたウインク.こちらを選択してZIP化した場合はファイルリストをS-JISに強制的に変換してからZIP化しますので,クライアントPCがWindowsでも大丈夫です.既にmoodleを運用しているサイトをfs_moodle化する際の移行時期に使う機能として用意したのですが,この部分の機能はLinuxをサーバとするmoodleサイトにとっても使える機能かも知れませんね.時間ができたらこの部分だけ抜き出してみましょうか?


unzipするソフトがUTF-8に対応していれば,多分,このような小細工を使わないで済むと思うのですが,私が常用しているソフトウェア(ExpLZH)は,つい先日までUTF-8に対応していなかったので,(ちょっと手の込む改造でしたが)対策しました.割と早い段階で行なった改造だったので,その後の悪い副作用が出ていないだろうか,あるいはもっと良いコーディングがあったのではないか,という不安はあります.

#今日中に雑用を済ませて,明日からまっさらなWindows環境にゼロからmoodleをインストールする実験を開始します.

Attachment SJIS-ZIP.jpg
In reply to Haruhiko Okumura

Re: 日本語ファイル名をIEでダウンロードするときの文字化け対策

by Tatsuya Shirai -
Moodle1.8.3+で,上記の修正($filename = urlencode($filename))が取り込まれました.ただし,file.phpではなく,lib/filelib.php中のsend_file()の中です.

Moodleを1.8.3+にアップデートする際には,上記の修正を外さないと$filenameを2度,urlencode()することになりますので御注意下さい.

なお,rawurlencode()ではなく,なぜurlencode()なのでしょう???

オリジナルのMoodleでは半角スペースを含むファイル名を許さない,ということになっているので問題はないようですが,当方の環境(fs_moodle)では半角空白をファイル名の一部に含むことを認めています.この環境下ではrawurlencode()で正しく半角空白を含むファイル名のファイルのダウンロードに成功しています.

#長いファイル名の場合はurlencode()(rawurlencode()も?)では問題が発生するとのことですので,シフトJIS化するか,URLエンコードするか,依然として悩ましいところですね.日本語Windowsがクライアントの大多数を占める日本では,ファイル名にシフトJISに存在しない文字を使用することはほとんど無い(有ったら化ける?)のでシフトJIS化が好ましいのですが.
In reply to Katsunori Mizuno

Re: 日本語ファイル名をIEでダウンロードするときの文字化け対策

by akihiro hashimoto -

okura先生からMoodleをならったばかりの初心者です。
Moodle 2.0 Cent OS5.1の環境下で,日本語が文字化けするので,以下のパッチを
適用しました。
*** filelib.php 2008-05-10 22:09:34.000000000 +0900
--- filelib.php-hash2008510.org 2008-05-10 22:05:37.000000000 +0900
***************
*** 545,556 ****
if (check_browser_version('MSIE')) {
$filename = urlencode($filename);
}
! // hashimoto modified 2008-05-10
! //
if ($forcedownload) {
! @header('Content-Disposition: attachment; filename="' . $filename . '"');
} else {
! @header('Content-Disposition: inline; filename="' . $filename . '"');
}
if ($lifetime > 0) {
--- 545,555 ----
if (check_browser_version('MSIE')) {
$filename = urlencode($filename);
}
!
if ($forcedownload) {
! @header('Content-Disposition: attachment; filename='.$filename);
} else {
! @header('Content-Disposition: inline; filename='.$filename);
}
if ($lifetime > 0) {
diff -c config.php config.php-hash2008510.org
*** config.php 2008-05-10 21:59:13.000000000 +0900
--- config.php-hash2008510.org 2008-05-10 21:57:01.000000000 +0900
***************
*** 9,20 ****
$CFG->dbpass = '@c37ddd';
$CFG->dbpersist = false;
$CFG->prefix = 'mdl_';
- // hashimoto added the next lines 2008-05-20
- $CFG->unicodedb = true;
- $CFG->unicodecleanfilename = true;
- //
- //
$CFG->wwwroot = 'http://dokokare.niigata-cn.ac.jp/moodle';
$CFG->dirroot = '/var/www/html/moodle';
$CFG->dataroot = '/var/www/moodledata';
--- 9,15 ----
diff -c file.php file.php-hash2008510.org
*** file.php 2008-05-10 22:04:23.000000000 +0900
--- file.php-hash2008510.org 2008-05-10 22:00:42.000000000 +0900
***************
*** 164,184 ****
// ========================================
session_write_close(); // unlock session during fileserving
$filename = $args[count($args)-1];
- // file namae hash modified the lines
- $ua = $_SERVER['HTTP_USER_AGENT'];
- if (strstr($ua, "MSIE") && !strstr($ua, 'Opera')) {
- $filename = mb_convert_encoding($filename, "SJIS", get_string('thischarset'));
- } elseif (strstr($ua, "Safari")) {
- if (get_string('thischarset') == "UTF-8") {
- $filename = "";
- } else {
- $filename = preg_replace('/[^\.a-zA-Z\d\_-]/', '_', $filename);
- }
- } else {
- $filename = mb_convert_encoding($filename, "UTF-8", get_string('thischarset'));
- }
- $filename = str_replace('#', '%23', $filename);
-
send_file($pathname, $filename, $lifetime, $CFG->filteruploadedfiles, false, $forcedownload);
function not_found($courseid) {
--- 164,169 ----

これによりFireFoxではdownload,uploadともOK
IE-7ではURLを汎用ドメインに対応したせいか?
以上のような症状ではなく, 「多変量解析Ⅱ.ppt」が
%8A%C5%8C%EC%8C%A4%8B%86%82%C6%93%9D%8Cv%93I%95%FB%96%40%81i%91%E5%8Aw%89%40%81j.ppt

としてUNICODEの16進形式なってしまいます。現在このパッチを作成しています。

(報告まで)

In reply to akihiro hashimoto

Re: 日本語ファイル名をIEでダウンロードするときの文字化け対策

by akihiro hashimoto -

自己Followします。

IE7側の設定を変更しました。(グループポリシーでドメイン全体を変えればよい)
これは,UTF-8 として URL を送信するオフにする ポリシー設定どおりに機能しないバグによるようです。

REGEDITで
ユーザーの構成⇒Windows コンポーネント⇒ Internet Explorer⇒管理用テンプレート ⇒インターネット設定⇒

で再度修正すればOKのようです。

参考

http://support.microsoft.com/kb/925261/en-us

Average of ratings: お役立ち度: ★★★★★★★ (1)
In reply to akihiro hashimoto

Re: 日本語ファイル名をIEでダウンロードするときの文字化け対策

by akihiro hashimoto -

説明が悪かったので追加しておきます。

HTTP HeaderにContent-Dispositionのレスポンスヘッダフィールドは、ユーザがその内容をファイルに保存したい場合,ファイル名を提案する事を指定するので,

 Content-Disposition: attachment; filename="filename.ext" 

となっているはず。(根拠 RFC 1806 Category: Experimental)
そこでContent-Disposition ヘッダの filename 属性を使うと、マルチパートデータとして転送されたデータのファイル名をデータの送信側できるけど,問題があるというのがRFC 2616の「15.5 Content-Disposition Issues」 . そして,我々の問題はFilenameがNon-ASCIIの場合。これは上のRFC 1806でなく, RFC 2231 でのMIMEに従ってエンコーディングすべき。 (日本語に関してはRFC 1468の改訂版が出たがattribute-char として使えない文字が出るのでNGとなった。)
RFC 2231 でのMIMEについてFirefox,safariは適切に対応しているが,IEはそうでなく,http://support.microsoft.com/kb/436616/
題名 「ファイルをダウンロードする ASP.NET Web ページで日本語ファイル名が文字化けする問題が発生する。」
原因は上記URLに
Content-Disposition ヘッダのパラメータの文字コードのエンコード方式に関しては、RFC2231 に基づくべきですが、現行の Internet Explorer はこのエンコード方式をサポートしていません。
とある通り。
回避策も上記に記載があるが,適切でないようですね。

上記はREGEDITではないくgpedit.mscです。問題点は100台中何台かはグループポリーから適用されないマシンがあること。。。

;-)

In reply to akihiro hashimoto

Re: 日本語ファイル名をIEでダウンロードするときの文字化け対策

by akihiro hashimoto -

初心者なので失敗 かぶりました。

http://docs.moodle.org/ja/%E5%A4%9A%E8%A8%80%E8%AA%9E%E5%AF%BE%E5%BF%9C%EF%BC%9AIE%E5%9B%BA%E6%9C%89%E3%81%AE%E5%95%8F%E9%A1%8C

で解決済みなようですね。

In reply to akihiro hashimoto

Re: 日本語ファイル名をIEでダウンロードするときの文字化け対策

by Tatsuya Shirai -

 丁度,本家の方でも少しずつ試行錯誤的に修正が施されている箇所のようですので,moodleDocsの記述も内容が少し古くなってしまっています。

 いまはこの箇所に関して,

http://moodle.org/mod/forum/discuss.php?d=94845

こちらの議論の方が話が近いのかも知れません。

In reply to Tatsuya Shirai

Re: 日本語ファイル名をIEでダウンロードするときの文字化け対策

by Haruhiko Okumura -
どうも,しらばくMoodleをさぼっていました。hashimoto先生のところの2.0がうまく動いているようでなによりです。うちも今度こそは2.0にしようと思っています(GPで金がつけばいいのですが)。

あと,概算要求が通ればe-Portfolioも始めます。こちらはMaharaか何かを徹底的に書き直すことになるかもしれません。