ファイルダウンロード時のファイル名が文字化けする対処法
ファイルをダウンロードするときのヘッダーは次のようになります。
header('Last-Modified: '. gmdate('D, d M Y H:i:s') .' GMT'); header('Content-Description: File Transfer'); header('Content-Type: application/octet-stream'); header('Content-Disposition: attachment; filename="'.$file_name.'"'); header('Content-Transfer-Encoding: binary'); header('Content-Length: ' . filesize($file_path));
[参考記事] SSL(HTTPS)でファイルのダウンロードができない場合
スポンサーリンク
ダウンロード時のファイル名の指定方法の仕様
ここでダウンロード時に保存されるファイル名として指定するのがContent-Disposition: filenameの部分です。
これはRFCではRFC1806で
Content-Disposition: attachment; filename=filename.ext
を使用するように定義されています。
RFC2616の『15.5 Content-Disposition Issues』でも取り上げられています。
ファイル名を「"(ダブルクオート)」で囲うことも可能です。
Content-Disposition: attachment; filename="filename.ext"
さらにこのファイル名の指定についてはRFC2231で定義されています。
RFC2231の仕様としてはファイル名のエンコードを指定することもできます。
Content-Disposition: attachment;filename*=iso-2022-jp'ja'%1B%24B%24%5B%244%24%5B%242%1B%28B.jpeg
ファイル名を分割することもできます。
Content-Disposition: attachment;filename*0*=iso-2022-jp'ja'%1B%24B%24%5B%244%24%5B%242%1B%28B;filename*1=.jpeg
ブラウザによる違い
FirefoxやSafariではこのRFC2231に準拠していますが、Internet Explorerでは準拠していません。
これはIEのサポートページに明記されています。
http://support.microsoft.com/kb/436616/
ファイルをダウンロードする ASP.NET Web ページで日本語ファイル名が文字化けする問題が発生する。
Internet Explorerでは、Content-Disposition ヘッダが送信された場合、送られてきたコンテンツをそのままブラウザで開かずにファイルダウンロードダイアログを表示するようになっています。 その際にこのヘッダの filename パラメータを利用している場合、このパラメータで渡されたファイル名をファイルの保存時の既定のファイル名にします。 ただし、クライアントコンピュータのロケールを日本語にしている場合、Internet Explorer ではこのパラメータで渡された文字列 (ファイル名) を Shift-JIS でエンコードされているものとして処理します。
Content-Disposition ヘッダのパラメータの文字コードのエンコード方式に関しては、RFC2231 に基づくべきですが、現行の Internet Explorer はこのエンコード方式をサポートしていません。
ここでIneternet Explorerではファイル名をShift-JISとするように書かれています。
しかしIEでは文字コードに5cや7cを含むものは文字化けします。
http://support.microsoft.com/kb/930938/ja
5Cや7Cを含む場合、その下位バイト(トレイルバイト)が5Fに変わり、文字化けします。
これを避けるためにURLエンコードをする方法もありますが、URLエンコードをするとファイル名(エンコード時の文字数)が189文字を超える場合には、ファイル名の先頭から文字が欠損します。
Mac OS Xはファイル名が日本語を含む場合、トラブルが続出します。
ファイル名が一般的でないUTF-8の形式(例えば「が」を「か」+「゛」として扱っている)になっているかららしい。
対処法としてはContent-Dispositionにファイル名を指定しないのが一般的のようです。
どうしてもファイル名を指定したい場合には、HTTPヘッダーではなく、URLを変更して、次のようにしてファイル名を渡す方法があります。
http://www.example.com/download.php/ファイル名.pdf
またMacOS Xでは、Content-Dispositionにファイル名を指定しても
Content-Type: application/octet-stream
とすると、プログラムなどでファイルをダウンロードさせる場合には拡張子が「.html」になります。 このためファイルの種類ごと拡張子ごとにContent-Typeを指定します。
使用できない文字
またASCII文字であっても次の文字は問題が発生します。文字 | 説明 |
---|---|
; | HTMLヘッダーの区切り文字のため、ファイル名がここで途切れる |
/ | 保存するPCのファイルシステムでフォルダ階層を表す区切り文字のため、このファイル名を使用することはできない |
? | Windowsでは、保存ボタンを押しても反応しなくなる |
# | Internet Explorerで『_(アンダーバー)』に変わったり、文字が消えたりする |
半角空白 | ファイル名がここで途切れる場合がある これはファイル名を「"(ダブルクオート)」で囲うとよい |
サンプルコード
これらを踏まえると、ファイルのダウンロード時のHTTPヘッダーを次のようにすると文字化けは回避されます。
$file_name = '【ファイル名】'; $ua = $_SERVER['HTTP_USER_AGENT']; $file_name = str_replace("?","",$file_name); $file_name = str_replace("/","",$file_name); $file_name = str_replace(";","",$file_name); $file_ext = strtolower(preg_replace("/^.*\.([^\.]+)$/","$1",$file_name)); if(!preg_match("/safari/i",$ua)){ header('Content-Type: application/octet-stream'); }else{ if($ext == 'pdf'){ header('Content-Type: application/pdf'); }elseif($ext == 'xls'){ header('Content-Type: application/vnd.ms-excel'); }elseif($ext == 'doc'){ header('Content-Type: application/msword'); }elseif($ext == 'ppt'){ header('Content-Type: application/vnd.ms-powerpoint'); }elseif($ext == 'csv'){ header('Content-Type: text/csv'); }elseif($ext == 'txt'){ header('Content-Type: text/plain'); }else{ header('Content-Type: application/octet-stream'); } } if(preg_match("/MSIE/i",$ua)){ if (strlen(rawurlencode($file_name)) > 21 * 3 * 3) { $file_name = mb_convert_encoding($file_name, "SJIS-win","UTF-8"); $file_name = str_replace('#', '%23', $file_name); }else{ $file_name = rawurlencode($file_name); } }elseif(preg_match("/chrome/i",$ua)){// Google Chromeには『Safari』という字が含まれる }elseif(preg_match("/safari/i",$ua)){// Safariでファイル名を指定しない場合 $file_name = ""; } header('Content-Disposition: attachment; filename="'.$file_name.'"');
関連記事
- コマンドやphpMyAdminで複数のデータベースに接続できるユーザーを作成する方法
- phpMyAdminで『information_schema』などを非表示にする方法
- ディレクトリが存在するにもかかわらず、『No such file or directory』エラーが出る
- PDO_MYSQLをインストールする方法
- PEAR・PECLをインストールする方法
- file_get_contentsで$http_response_headerを使用するときの注意点
- サイトの更新情報をPINGサーバに送信する方法
- インクルードパスを設定する方法
- HEADリクエストを排除してサーバ負荷を軽減させる
- cron実行時の標準出力のメールを飛ばさない方法(cron実行時に毎回メールを飛ばさない)
- cron実行時のPATHなどの環境変数を確認する方法
- cronのメール送信先を指定する方法(cronごとに送信先のメールアドレスを指定する方法)
- cron実行時に『/bin/sh: 〜〜: command not found』と出てcronが実行されない場合
- 『crontab -r』でcronの設定を間違って消してしまった場合の対処法
- 日本語名のフォルダを作成する場合の注意点
- rename()を実行すると『Operation not permitted』とエラーが表示される
- cronを実行すると『TERM environment variable not set.』というエラーメールが飛ぶ
- 「ID」や「ID_xxxx」という文字列があるCSVファイルをExcelで開くとSYLKエラーが出る
- Excelの日付が数字になるときの対処法
- PHPでfacebook投稿時に公開範囲を指定する方法
- PHPで複数の画像をfacebookに投稿する方法
- PHPでfacebookのフィード(ウォール)に投稿する方法
- PHPでのfacebookアプリの認証処理(APIを使うユーザー認証)
- facebook APIを使用する時にfacebook Appsでアプリを登録するまでの流れ
- SELECTタグで色を選択する場合のサンプル
- POSTでアップロードできるファイルサイズの制限を変更する方法
- Zend Optimizerのインストール
- Zend Serverとは
- Live Commerceとは
- SSL(HTTPS)でファイルのダウンロードができない場合
- simplexml_load_file()、simplexml_load_string()でparser error : Input is not proper UTF-8, indicate encoding !
- Deprecatedエラーを消す方法 (php.iniや.htaccess)
- Cactiのインストール RRDToolを利用したサーバ監視ツール
- JISコードでstrlenの文字数が合わない(目視の文字数とstrlenの文字数が異なる)
- echoしても文字は表示されないのに、emptyがtrueにならない
- [暗号化]ブロック暗号とは(AES/DES/Blowfish PKCS5Padding ECB/CBC IV)
- == と === の違い(比較演算子)
- Firefox、Chromeなどで文字化けを防ぐ方法 ヘッダー情報に文字コードを指定
- CakePHP、Symfony、Zend Frameworkの比較
- ブラウザの中止ボタンを押した後も処理を実行させる方法 タイムアウト以外の停止
- HTMLファイルのエンコードを『内容から判別する』にしない方法
- SQL Buddy ブラウザベースのMySQL管理ツール
- Twitter APIを使用する (Twitterアプリケーション登録)
- Mantisのインストール
- Mantisのユーザー管理テーブル(mantis_user_table)
- create_functionでメソッドを使用する方法
- strtotimeでmonthを使用するときの注意点
- コマンドラインからpearを実行するとエラーが出る 環境変数PHP_PEAR_PHP_BINの設定
- PEARを更新する方法
- zend_mm_heap corrupted とは
- switch文とif文の違い
- fgetcsv関数を文字化け対応 setlocaleの文字コード指定
- Deprecatedの修正例(POSIX)
- Fatal error: Call to undefined function imagecreatefromjpeg() の対処法
- PHPをyumでインストールする
- php_network_getaddresses: getaddrinfo failed: Temporary failure in name resolutionの対応
- fsockopenでSSLサーバに接続する
- PHPでPDFファイルを作成する FPDF FPDI TCPDF
- 『このインターネットのサイトを開くことができません。』と出て、ファイルをダウンロードできない
- 複雑なExcelファイルをプログラムで作成する方法
- Excelで保存したときのCSVファイルの仕様
- フォーム要素の属性名の『ドット( . )』は『アンダーバー( _ )』に変わります
- サブドメインにアンダーバーがあるとクッキーは使えない
- アンダーバーのあるドメインではセッションクッキーは使用できません
- NetBeans6のインストール(JavaだけでなくRuby、PHP、C/C++に対応した統合開発環境)
- memcachedを使用する(memcacheライブラリ)
- date.timezoneを設定するとPHPが早くなる
- PHPフレームワークの一覧
- mbstringエミュレータ
- Fatal error: Maximum execution time of 30 seconds exceededの対処法
- PHPのインストール
- 例外処理(Exception)
- Windows版PHPにPEAR・PECLをインストールする
- PHPをコマンドラインから使用する方法
- 画像の保存やメール転送を制限する方法
- PHPの閉じタグは書いてはいけない
- $_SERVER['PHP_SELF']は危険?
- Net_UserAgent_Mobile 携帯判別PEARパッケージの使い方と注意点
- stdClassクラスとは
- ユーザーエージェントからのキャリア、世代判別
- クラスとオブジェクト
- str関数、preg関数、ereg関数の速度比較
- 配列値格納の構文と組み込み関数による速度比較
- 正規表現のパターン文字列に日本語文字を使うときの注意
- ダブルクオート/シングルクオート/ヒアドキュメント、echo/printの速度比較
- forとforeachの速度比較
- SJISじゃなくてSJIS-win、EUC-JPじゃなくてeucJP-winを使おう
- 文字列の一部を得る関数mb_substrとmb_strcutの違い
- mb_strlenやmb_strimwidthの注意点
- failed: No space left on device
- VGA端末用に出力画像を拡大縮小する方法
- VGA端末の画像表示対応
- SSL通信かどうか
- docomo端末でCSSを使うには
- yumで、より新しいパッケージをインストールする方法(CentOS)
- 住所や駅名などから緯度経度を取得する
- empty関数について
- $_REQUESTに入る値と、その優先順位
- mail関数やmb_send_mail関数でReturn-Pathを設定する方法
- 携帯サイトのmailtoを端末ごとに書き換える関数
- MySQLのソケットエラー
- EclipseでPHPプロジェクトにする方法
- Softbankの携帯で文字の色を白にするときは注意
- mailtoの使い方
- 携帯サイトでのmailtoの使い方
- mailto本文での改行 ドコモのN、Pで送信に失敗します
- 数字(0〜9)のみかどうかを調べる正しい方法
- PCからデコメールを送るときの仕様
- PHPのバージョン表記の隠蔽
- quoted-printable文字列の変換
- Mantisのメール文字化け
- Issue-Tracker [バグ追跡システム]
- phpBugTracker [バグ追跡システム]
- eGroupWare [バグ追跡システム]
- OpenTask [バグ追跡システム]
- <docomo>タグ、<au>タグ、<softbank>タグの使用例
- 動的ページを静的ページに偽装する方法
- 『サイトが移動しました』を出さない方法
- セッション固定攻撃(session fixation)
- Softbankで絵文字を表示させる
- 位置情報・GPS情報の取得方法
- サイトを公開するときの設定
- クッキー(cookie)について
- セッションの有効期間とか設定とか挙動とかを調べました
- 携帯電話端末の判別ライブラリ Net_UserAgent_Mobile
- 個体識別情報・UIDの取得方法
- OpenPNEのツッコミどころ
- magic_quotes_gpc = On の対策
- Windows版PHPのインストール
- Mantis(マンティス) バグ管理システム
- CakePHP
- Symfony(シンフォニー)
- EC-CUBE
- Zen Cart(ゼン・カート)
- OsCommerce
- OpenPNE
- PukiWiki
- MediaWiki
- Wordpress
- Nucleus
- Movable Type
- NetCommons(ネットコモンズ)
- Joomla(ジュームラ)
- Drupal(ドルーパル)
- XOOPS Cube
- Geeklog(ギークログ)
- UTF-8からSJISで文字化け
- ファイル操作
- Smarty
- 正規表現
- ちいたん
- Symfony
- サンプルコード
- EC-CUBE
- Zend Framework
- Ethna
- OpenPNE
- CakePHP
- WordPress
- XOOPS Cube
- Drupal(ドルーパル)
- FPDF 1.52 リファレンス
- Doctrine
- 講座
- Yii
- Live Commerce
スポンサーリンク