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

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

- M O の投稿
返信数: 22
お世話になっております。
MOです。

現在私の環境はRedHat EL4+moodle1.8+
です。RedHat EL4からUTF-8が標準のようです。

最近までEL3(EUC)試していたのですが、
EL4で試すようになってからIEでのダウンロードが
調子が悪いです。

既知の問題で「file.php」の
$filename = mb_convert_encoding($filename,SJIS", "UTF-8");を
$filename = urlencode($filename);に修正すると
文字化けせずにダウンロードできるとのことでした。
しかし、私の現在の環境でうまくいきませんでした。

状況としては、
コースのリソース追加からファイルをアップロードすると
「moodledata」のフォルダ内には正しい日本語名でファイルがアップされるにも関わらず、ダウンロードのリンクに文字化けしたファイル名で呼び出しを行い、ファイルが無いとエラー表示がでます。

どなたか、このエラーの原因を追究している方がいれば
教えて頂けると助かります。

いくつか参照させて頂いた情報を下記に示します。
http://docs.moodle.org/ja/サイトファイル
http://oku.edu.mie-u.ac.jp/~okumura/linux/?Moodle
http://moodle.org/mod/forum/discuss.php?d=72567
M O への返信

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

- Tatsuya Shirai の投稿
当方の環境で改造中の箇所のうちの一つが,まさにその部分です.
これはアップロードされているファイルのリストからダウンロードする場合だけであって,もしかしたらフォーラムにアップロードされたファイルやウェブページの場合にはうまくいかない可能性もあります.

かならずrawurlencode()してしまえば,FirefoxだろうとIEだろうと同じ,という意味で,MOさんの仰る通りに改善になっているはずです.

mod/assignment/type/upload/assignment.class.libのprint_user_files()を以下のように変更.
if ($basedir = $this->file_area($userid)) {
if ($files = get_directory_list($basedir, 'responses')) {
require_once($CFG->libdir.'/filelib.php');
foreach ($files as $key => $file) {

$icon = mimeinfo('icon', $file);

// $ffurl = "$CFG->wwwroot/file.php?file=/$filearea/$file";
$ffurl = "$CFG->wwwroot/file.php?file=/$filearea/" . rawurlencode($file);


$output .= '<a href="'.$ffurl.'" ><img src="'.$CFG->pixpath.'/f/'.$icon.'" class="icon" alt="'.$icon.'" />'.$file.'</a>';
Tatsuya Shirai への返信

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

- M O の投稿
MOです。
早い返信ありがとうございます。

ということは、対象となるファイルのURL作成時のファイル名のエンコードを「rawurlencode」で変更してやればおそらく動作が正しく行われるということですね?


M O への返信

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

- Tatsuya Shirai の投稿
そうですね.
ハイパーリンクのhtmlコードをechoしている箇所と云うのはあちこちにあるし,しかも総じて読みにくいため追跡が意外と大変でしたが,あの例示した箇所だけで,当方は特に問題なくIEでダウンロードできています.

あの箇所で,$fileはUTF-8のファイル名そのままです.
ブラウザがそこ(<a> href="ほにゃらら" </a>)をクリックしてファイル名をサーバ側に送る際に,Firefoxはエンコードして送信するのに対して,IEはUTF-8のまま送信するため,サーバ側で受けた際に奥村先生たちが示したfile.phpの修正が必要だったのでした.そういう意味ではあの箇所を修正すればfile.phpの対策は不要なのかも知れませんが,file.phpは色々なところから利用されるため,当方でもfile.phpの対策はそのまま残しています.


Tatsuya Shirai への返信

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

- M O の投稿
MOです返信が遅れてすいません。

Tatsuya Shiraiさんのご指摘どおり修正したのですが
動作が正しくありません。
画像を添付してみました。

Tatsuya Shiraiさんの環境をお聞きしてもよろしいですか?参考にさせてください。

以上です。

M O への返信

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

- Tatsuya Shirai の投稿
画像を確認しました.
おかしいですねぇ.
あの修正を行なうことで,ブラウザのアドレス欄にURLエンコードされた文字が表示されるはずなのですが...

htmlソースではどうなっていますか?
オリジナルのコードですと日本語ファイル名が,変更したコードですととrawurlencodeされた%16進数の文字列がページのソースのhref=の右側に入っているはずです.

Tatsuya Shirai への返信

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

- M O の投稿
すいまんせん。
どのページのソースでしょうか?

アップさせて頂いた2つの画像のどちらにも、16進数のリンクは貼られていませんでした。
mod/assignment/type/upload/assignment.class.phpの
print_user_files()の部分は変更したんですが、/moodle/course/view.phpや
/moodle/file.phpに影響を与えているような動作はしていない気がします。




M O への返信

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

- Tatsuya Shirai の投稿
いや,すみません!大きな勘違いでした.
私が示したのは,”課題”のリソースがIEでダウンロードできない場合の対策でした.

いま即席で対策してみたところ,失敗しました.
もう少し解析しなおしてみます.

Tatsuya Shirai への返信

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

- Tatsuya Shirai の投稿
file.phpの以下の箇所の修正を試していただけませんか? 900行目前後です.$filelistの表示の前に,良く似たコードで,$dirlistの表示を行なっています.そちらと間違えないように!

if (!empty($filelist)) {
asort($filelist);
foreach ($filelist as $file) {

$icon = mimeinfo("icon", $file);

$count++;
$filename = $fullpath."/".$file;
$fileurl = trim($wdir, "/")."/$file";
$filesafe = rawurlencode($file);
$fileurlsafe = rawurlencode($fileurl);

この$fileurlがリンク先のアドレスとして使用されています.
$filesafe, $fileurlsafeは思わせぶりに存在するのですが,パッと見た感じでは使用されていません.

試してみることとして以下の2つがあります.
(1) $fileurl = $fileurlsafe;
これをこのまま直後に記述して$fileurlを上書きする.これで良いと思ったのですが,当方の環境ではうまく行きませんでした.パスの/や何故か拡張子までエンコードされてしまいました.もしこの方法でブラウザから「Object not found!」とエラーを返された場合(当方はこうなります)は,以下のコードを試して見て下さい.パスやファイル名のみをrawurlencodeします.

(2)上の方法でダメな場合.
$path_parts = mb_split("/", $fileurl);
foreach ($path_parts as $key => $path) {
if ($key == 0) $fileurl = rawurlencode($path);
else $fileurl .= "/".rawurlencode($path);
}

これでブラウザでファイル名にカーソルを持っていくと,URLエンコードされたアドレスがfile.php/以降に表示されるはずです.

ただ,なんとなく問題から逃げているような気もしますが!
(apache/php等の設定かも知れませんね)
Tatsuya Shirai への返信

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

- M O の投稿
MOです。
すいません、返信が遅れて。。;
Shirai さんがいっている「file.php」はmoodle直下のファイルのことですか?

私のは900行もないので、別のディレクトリかと思っているのですが。
どこのファイルでしょうか?

>(apache/php等の設定かも知れませんね)
そうなんですよ、この設定も確かに疑わないといけないんですよね。
ただ、RHEL3では全て上手くいってたんですよ。
OSの文字コードがEUC→UTF-8に変更されているので影響を受けているのでしょう。
UTF-8からEUCに変更するとOSのサポート対象外になるので、変更したくない気持ちもあるんですよねぇ。
M O への返信

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

- Tatsuya Shirai の投稿
すみません,またまたボケてしまいました赤面

file.phpではなく,files/index.php です.

もしこの修正でうまくIEでもダウンロードできるようになるとすると...他にも数箇所変更が必要ということになりそうですウインク. うまく行かないことを祈ります...

具体的に言いますと,HTMLエディタでで画像やリンクを貼ったり,張ったり,する際にもファイル編集画面が表示されますよね.これらも良く似たdisplaydir()という関数を利用しています.(lib/editor/htmlarea/coursefile.php) 統一してくれると修正が楽なのですが...
Tatsuya Shirai への返信

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

- M O の投稿
ん~~上手くいかないですねぇ。悲しい
URLもエンコードが上手くいってない感じです。

エンコードという意味だと
moodle/mod/resource/type/file以下にある
「resource.class.php」の314行目程度にある$fullurl変数を
以下のコードで変更すると一応正しくURLにファイル名は入力されるのですが、
結局ダウンロードできず・・・
$ua = $_SERVER['HTTP_USER_AGENT'];
if (strstr($ua, "MSIE") && !strstr($ua, 'Opera')) {
$fullurl = mb_convert_encoding($fullurl, "SJIS", get_string('thischarset')); }else{
$fullurl = mb_convert_encoding($fullurl, "UTF8", get_string('thischarset'));
}

運用で話をしたら、ファイル名を英数字で対応していくようにまとまりそうですが
なんとか、したいものですね。

長々とありがとうございました。
今後とも宜しくおねがいします。

M O への返信

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

- Haruhiko Okumura の投稿
なんででしょうね。うちでは問題なさそうなんですが。
EL3とEL4の違いというのは関係ないと思います。
httpd.confとphp.iniに何が書いてあるかの問題でしょう。
Haruhiko Okumura への返信

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

- Tatsuya Shirai の投稿
すみません,リソースでしたね.どうもピントがズレたことばかりしています.

当方の環境はWindowsですのであまり参考にならないかと思いますが,
php.iniのmbstring関係の設定を以下のように行なっています.
正しいという保証はありません.

[mbstring]
mbstring.language = Japanese
mbstring.internal_encoding = "UTF-8"
mbstring.http_output = "UTF-8"
mbstring.encoding_translation = On
mbstring.func_overload = 0

余計なコメントや未設定の項目は省略しています.


Tatsuya Shirai への返信

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

- M O の投稿
php.iniの設定は同じですねぇ。
httpd.confの設定ももう一度確認してみます。
M O への返信

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

- Haruhiko Okumura の投稿
もしEL3でうまくいっていたのでしたら,そのhttpd.confやphp.iniを持って来たらどうなるでしょうか。
Haruhiko Okumura への返信

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

- M O の投稿
状況がかわりませんでした。
しかし、調査してみるとEL3の時はRPMでインストールしたが
EL4ではソースからコンパイルしている状況が発覚しました。

もう少し環境周りでも調べたいと思います。

M O への返信

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

- Tatsuya Shirai の投稿
白井です.

少々気になるのは,IE向けの対策としてfile.phpに施した対策ですが,現在のトレンドは以下のような修正だと思うのですが,いかがでしょう?
// ========================================
// finally send the file
// ========================================
session_write_close(); // unlock session during fileserving
$filename = $args[count($args)-1];
/// (ここから)
$ua = $_SERVER['HTTP_USER_AGENT'];
if (strstr($ua, "MSIE") && !strstr($ua, 'Opera')) {
// $filename = mb_convert_encoding($filename, "CP932", "UTF-8");
$filename = urlencode($filename);
} else if (strstr($ua, "Safari")) {
$filename = "";
}
$filename = str_replace('#', '%23', $filename);
/// (ここまで)
send_file($pathname, $filename, $lifetime, $CFG->filteruploadedfiles, false, $forcedownload);

元々は上記のように"UTF-8"から"CP932"(S-JIS)へ変換するというものでしたね.ただ,気になるのは,この対策は「IEでファイルをダウンロードすると名前が化ける」という問題だったと記憶しています.MOさんの現状は,file.phpが「ファイルが見つからない」というエラーを出すのですよね? であるならば,上記コードで行なう対策とは別の要素が問題となっているのではないでしょうか.お話から察するに,上記コードの直前にある,
// check that file exists
if (!file_exists($pathname)) {
not_found($course->id);
}
こちらのエラーに引っ掛かっている,つまり問題は$pathnameの方ではないでしょうか?($filenameはクライアントPC側で再現すべきファイル名) mod/resource/type/file/resource.class.phpのdisplay()にてURLエンコードを行なってfile.phpをうまく(文字化けしないでUTF-8の名前で)呼び出せたのであれば,この$pathnameも正しいと思います.$pathnameがどういうことになっているのかを確認できないでしょうか.大元を辿ると,$pathnameは,
$relativepath = get_file_argument('file.php');
が,
$pathname = $CFG->dataroot.$relativepath;
のように合体したものです.$pathnameの正当性(余分な/が付いていないか,などのチェック)はほとんど行なわれていません.

ところで,file.phpのデバッグはechoを行なっても画面に文字表示を行なえないため,面倒ですよね.PHPのデバッグツールをお持ちならば良いのですが(私は準備していません...),そうでないならば,以下のような感じで,function not_found()を改造して$pathnameの値を画面に表示・確認してみては如何でしょうか.

(1) file not found 検出
// check that file exists
if (!file_exists($pathname)) {
not_found($course->id, $pathname);
}

(2) error表示
function not_found($courseid, $str="") {
global $CFG;
header('HTTP/1.0 404 not found');
// error(get_string('filenotfound', 'error'), $CFG->wwwroot.'/course/view.php?id='.$courseid); //this is not displayed on IIS??
error("[$str]", $CFG->wwwroot.'/course/view.php?id='.$courseid); //this is not displayed on IIS??
}


Tatsuya Shirai への返信

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

- M O の投稿
すいません、いろいろ調べてもらってしまって・・・恥ずかしい

現状、まだダウンロードはできていません。
しかし、アドレスバーに正しいパスで日本語ファイル名を表示できています。
でも、「ファイルは見つかりません」といわれます。
そこで更にアドレスバーをクリックすると、ブラウザ上にバイナリデータが羅列されます。
つまり、パスは文字化けさえなければ、正しいものであると考えています。
リンククリック時に、なぜ「見つかりません」と言われるのは謎ですが・・・

ファイルも添付させていただきました。
本当にありがとうございます。
M O への返信

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

- Tatsuya Shirai の投稿
moodleでは,実際のファイルがある場所を隠匿していますので,Webサーバ(apache)等のようにダイレクトにURLアドレスで表示はできません.全てfile.phpを介してファイルの送信を行なうはずです.したがって,ブラウザのアドレスバーをクリックして,apache等がファイルを送信している訳ではないはずですので,バイナリーデータがブラウザ画面上に表示されるのが謎です.http手順でファイルを送信する際に,そのファイルの種類に応じて(mimeでしたか?)アプリケーションを立ち上げるのか,ダウンロードさせるのか,画面に表示させるのか,apacheのメカニズムがうまく働いていないのでしょうね.

ファイルが見つからない,という表示は,apacheが表示しているものなのか,それともmoodleが表示しているものなのか,です.もし添付したような画面が表示されるならばmoodleが出しているエラー画面であり,それは,

// check that file exists
if (!file_exists($pathname)) {
not_found($course->id);
}
ここで表示されています.つまり外部からは隠匿されているmoodledata以下の実際のファイルのフルパス名を表す$pathnameでファイルの有無を確認した結果,file_exists()で発見できなかったことを意味します.ですので,この$pathnameがmod/resource/type/file/resource.class.phpのdisplay()から呼ばれた場合と,ブラウザのアドレス欄をクリックし直した場合とで異なることが理由の一つでしょう.

どちらからfile.phpを呼び出してもfile_exists()をパスできればapacheを介してファイルがブラウザに向けて送信されます.それがダウンロードされたりアプリケーションで起動するか,あるいは画面表示されるかは,apacheの設定によると思います.apacheはファイルの拡張子によってファイルの種別を判断しているのかな? もしかしたらここの処理もmoodleが行なってmime設定を生成しているとすると,拡張子をうまく認識できていないのかも知れませんね.マルチバイトの文字列に対するpathinfo()かbasename()がうまく機能していないのかも知れません.こちらを確認するには,

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

を参照し,ご自身の環境で試して見て下さい.


添付 filenotfound.jpg
Tatsuya Shirai への返信

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

- Tatsuya Shirai の投稿
重要な確認です.
IE以外ならばダウンロードできるという前提で宜しいのでしょうか?
Firefox等でならばダウンロードが正常に行なえるのでしょうか.
もし,[サイト管理]-[サーバ]-[動作環境]で表示されるphpの設定で,iconv以降の欄の右端がOKでないならば,Firefox等でも正しく日本語のファイルをダウンロードできない可能性が高いです.PHPもソースからコンパイルしたのであれば,mbstring等がコンパイルオプションで有効になっていなかったか(コンパイルしたことが無いので分かりません),あるいはモジュールをロードするのかも知れませんが,その設定が行なわれていないということが考えられます.

それと,moodleではなく,MOさんの環境のapacheの普通のWebページにおいて,日本語ファイル名のExcelファイルのダウンロードはIEからでも正常に行うことができるのでしょうか? moodleのフォルダにhtmlファイルとエクセルのファイルを置いて確認できると思います.これでExcelが画面にバイナリーデータとして表示されるのならば問題はapacheのmimeの設定が疑われますし,Excelのファイル名を英数字に変えるとダウンロード(あるいはアプリケーションから起動)されるのであれば同じくapacheの日本語パス名に対する取り扱いが正しく機能していない結果,mime設定が正しく機能できなかったということでしょう.



Tatsuya Shirai への返信

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

- M O の投稿
>IE以外ならばダウンロードできるという前提で宜しいのでしょうか?
できています。

>[サイト管理]-[サーバ]-[動作環境]で表示されるphpの設定
すべてOK表示です。

>日本語ファイル名のExcelファイルのダウンロードはIEからでも正常に行うことができる
>のでしょうか?
IEはできました。逆にFireFOXでできませんでした。
Firefoxはアドレスバーで文字化けを起こしていました。
Operaもいけました。

なんとなく、設定の問題な気がしてきました。