まだよくわかっていないことが多いので,お気づきの点がありましたらご教示ください。
[2006-05-08] WindowsのIEで化けていた(^^;)ので直しました。
[2007-03-14] IE5/6はUTF-8をURLエンコードした名前でもOKだそうです(Thanks: 白水さん)。
日本語ファイル名の扱い方はブラウザによって異なり,たいへん厄介です。
まず,ファイル名はURLのパスとして与えることができます:
<a href="fakefile.php/日本語ファイル名.txt">クリックしてね</a>
この場合,ブラウザは「日本語ファイル名.txt」というファイルを見ているつもりになりますが,サーバ側では fakefile.php を実行し,/日本語ファイル名.txt はその実行の際に環境変数 PATH_INFO として渡されるだけです。
また,ファイル名はHTTPヘッダによっても与えることができます:
Content-Type: text/plain; charset=UTF-8 Content-Disposition: attachment; filename="日本語ファイル名.txt"
ブラウザはこのどちらのファイル名を見るかという問題と,それらのファイル名をどういうエンコーディングにすればいいかという問題があります。
まず考えられるのはUTF-8で,今後はこれが主流になっていくと思いますが,IEはファイル名についてはまだShift JISでないと文字化けするようです。
さらに,URLエンコード(%に続く2桁の16進表記)するか,RFC 2047流にMIMEエンコード(=?ISO-2022-JP?B?....?=
のような形式)するか,それとも生のままにするか,という問題があります。
また,RFC 2231によれば filename*=iso-2022-jp'ja'URLエンコードされたファイル名
のように書くのが正しそうです。
また,少なくともURLに含ませる場合は,特殊文字の扱いには要注意です。
例えば 日本語#ファイル.txt
と書くと 日本語.txt のように扱われてしまうので,日本語%23ファイル.txt
のようにURLエンコードしなければならないようです。
PHPで生成したファイルを日本語ファイル名でダウンロードさせます。
飛び先の fakefile.php は次のようになっています:
<?php
if (isset($_SERVER['PATH_INFO'])) {
$filename = substr($_SERVER['PATH_INFO'], 1);
} else {
$filename = "不明.txt";
}
$ext = substr($filename, -4);
if ($ext == '.txt')
$type = 'text/plain';
else
$type = 'application/octet-stream';
$ua = $_SERVER['HTTP_USER_AGENT'];
if (strstr($ua, 'MSIE') && !strstr($ua, 'Opera')) {
// IE(オペラの仮装でない)はSJISにしないと化ける
$filename = mb_convert_encoding($filename, "SJIS", "UTF-8");
// $filename = urlencode($filename);
$content = 'あなたのブラウザはIEですね。';
} elseif (strstr($ua, "Safari")) {
// どうやっても化けるのでContent-Dispositionでなく
// URLの最後の部分(PATH_INFO)でファイル名を指定
$filename = "";
$content = 'あなたのブラウザはSafariですね。';
} else {
// $filename = '=?UTF-8?B?' . base64_encode($filename) . '?=';
$content = 'あなたのブラウザはIEでもSafariでもありませんね。';
}
header('Content-Type: ' . $type);
header('Content-Disposition: attachment; filename="' . $filename . '"');
echo $content, "\n";
?>
Last modified: