日本語ファイル名

まだよくわかっていないことが多いので,お気づきの点がありましたらご教示ください。

[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: