質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

Q&A

解決済

3回答

18233閲覧

PHP $FILESで受け取った文字が文字化け

Brownie

総合スコア71

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

0グッド

2クリップ

投稿2015/10/15 05:53

何時間もはまってしまいました。
ご存じの方がいれば、ご教授願います。

PHPの$FILESで受け取った段階で文字化けが起きてしまい、困っています。

添付ファイルを $_FILES でうけっとた際に日本語名が「????????」となってしまう現象です。

・サーバーの設定はUTF8
・ファイルはUTF8
・mb_convert_encodingで変換できず
日本語だけが文字化けする事と「???????」という特徴的な化け方をするという事しかわかっていません。


$_FILES['mail']['name'] ← ??????????.txt

といった具合です。

HTMLはこのようになっています。

<form method="post" action="sendmail.php" enctype="multipart/form-data" > <input type='file' name='mail'> //サブミット </form> ------------------------------------------------------------------

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2015/10/15 06:33

php.iniなどで与えられる、mbstring設定、特にmbstring.detect_order、mbstring.internal_encoding、mbstring.encoding_translationを示してください
Brownie

2015/10/15 06:54 編集

[mbstring.language = Japanese] [;mbstring.detect_order = auto] [mbstring.internal_encoding = UTF-8] [mbstring.internal_encoding = UTF-8] [;mbstring.encoding_translation = Off]
Brownie

2015/10/15 06:54

情報追加依頼、有難うございます!php.iniから抜粋しました。
guest

回答3

0

$_FILES['upfile']['name'] の文字化けが気になるということは…

その値を何かに利用しようということでしょうが、セキュリティ上の脆弱性を埋め込んでしまう恐れがあるということは認識の上でしょうか?

おそらく、質問者様の環境は、クライアントがwindowsで、サーバーがLinux の環境というものと推察いたします。

Windows だと、拡張子がないファイルはアプリケーションの関連付けがされずに不便なので、ファイルには拡張子が存在するものと考えても問題ありませんが、MacやLinuxの場合、拡張子がなくても適したアプリケーションに関連付けされますので、アップロードされるファイルに必ずしも拡張子が付いているとは限りません

また、Mac, Linux の場合、エンコードはUTF-8 であるので、アップロードされたファイルのファイル名がSJIS-WIN であることを前提にプログラムを組むことができません。

また、.exampleのように ドット+文字列のようなファイルを作成することが可能.htaccessでおなじみの形式です。このようなファイル名を設定したファイルをアップロードされると、プログラムは破綻してしまいますね。

例えは、$_FILESvar_dump() で出力すると、

array (size=1) 'upfile' => array (size=5) 'name' => string 'sample.php' (length=10) 'type' => string 'text/x-php' (length=10) 'tmp_name' => string '/tmp/php7O5wLi' (length=14) 'error' => int 0 'size' => int 115

のような値が出力されますが、

$_FILES['upfile']['name'] はユーザーが任意で設定可能な値で、これを無条件に受け入れること自体がナンセンス。

実行可能な .exe の拡張子を .txt, .jpg に置き換えてアップロードすることは容易であるから。

では、$_FILES['upfile']['type'] ならば安全かというと否。
(参照) http://php.net/manual/ja/features.file-upload.post-method.php

公式マニュアルに書かれています。

ファイルの MIME 型。ただし、ブラウザがこの情報を提供する場合。 例えば、"image/gif" のようになります。この MIME 型は PHP 側ではチェックされません。そのため、 この値は信用できません。

アップロードされたファイルの妥当性は以下の関数を使ってチェックするのが普通です。
finfo_file

では、ファイル名はどうすればいいのかということですが、uniqid() とか、sha1_file() とかでランダムに設定するのが一番安全だよねってことになります。

参考サイト
ファイルアップロードの例外処理はこれぐらいしないと気が済まない

投稿2015/10/15 08:42

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Brownie

2015/10/15 08:53

メッセージ有難うございます! 正直、理解が難しいので何度も読み返しているのですが それだとアップロードファイル名は、取得できない、という結果になりませんでしょうか? アップロードしたファイル名を取得することが1番の目的となります。 そのため、以下の処理を考えました。 -------------------------------------------------------------- まず、フォームサブミットのボタンが押された際にjs関数を発火 関数内で、フォームにセットされているファイル名を取得して input hiddenで待機させている場所にファイル名をセット ファイル名だけ$_FILESとしてでなく$_POSTで受け取る $_POSTで受け取った値をDBに保存して使う ----------------------------------------------------------
退会済みユーザー

退会済みユーザー

2015/10/15 09:07 編集

> アップロードファイル名は、取得できない というより、「使用してはいけない」です。少なくとも、ファイルを保存する時のファイル名としてはいけません。 こんな使い方はアウトです。 move_uploaded_file($_FILES['upfile']['tmp_name'], UP_DIR . $_FILES['upfile']['name']); あくまで、ファイルを保存する時は、sample.txt が来ようと、hbavgabvbhsbfjacbhy27rh83hc3y73.txt のようにサーバーに保存しておき、ダウンロード用途のために、マルチバイト用のファイル名(ex. 日本語.txt)を別に(DBなど)に用意することは問題ありません。 ただし、ユーザーのアップロードするファイル名は任意で設定可能なので、バリデート処理をしっかり行って、ファイル名が取得できなかった場合にどうするのかをしっかり考慮しておきましょうということです。
Brownie

2015/10/15 22:59 編集

丁寧に説明して頂き、有難うございます! もちろん見えない部分では、保存時のファイル名をユニークにつけています。 アップロードされたファイル名を、ダウンロードする際につける名前として アップロードしたファイル名をDB上に保存しておくために 取得したいという事でご相談させていただきました。 大変勉強になりました、有難うございます! 長文でご説明していただき、非常に感謝します。
guest

0

ベストアンサー

私もかつて同じ現象で悩みいろいろ調べたのですが、どうもサーバー側の物理ファイル名称の文字コードがらみの問題らしく文字コード変換等では対応できず、直接的な対応方法を見つけることができませんでした。

そこで、回避策としてformのサブミット段階で、選択したファイル名称を、別の入力項目として送信する方法で対応しました。

以下にサンプルコードを記載いたします。
参考になれば幸いです。

html

1<script type="text/javascript"> 2function name_set() 3{ 4 document.all.maile_name.value = document.all.mail.value; 5} 6</script> 7 8 9<form method="post" action="sendmail.php" enctype="multipart/form-data" onsubmit="name_set();"> 10<input type='file' name='mail'> 11//サブミット 12</form> 13 14※サブミットした段階で、javascriptを使って、フォームのパラメータに選択したファイル名称を新たなパラメータとして盛り込んでいます。 15

■受け取り側

php

1 2 // ファイル名称を反転 3 $file = strrev($_FILES['mail']['name']); 4 5 // 頭からピリオードまでの文字を取得 6 $ext = substr( $file, 0, strpos( $file, "." ) ); 7 8 // 文字を反転して、元に戻す 9 $ext = strrev( $ext ); 10 11 // 拡張子を小文字に変換 12 $ext = strtoLower($ext); 13 14 // 名称をセット 15 $file_name = $_REQUEST["mail_name"] . $ext; 16 17$_REQUESTパラメータ取得時の各種チェック処理の記述は省略しています

投稿2015/10/15 07:27

編集2015/10/15 07:30
KenjiObata

総合スコア440

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Brownie

2015/10/15 07:37

なるほど! 一見、対症療法のようですが解決策があったとは大変嬉しいです。 大変助かりました。心よりお礼申し上げます。
guest

0

mb_convert_encoding()の第3パラメータfrom_encodingで'sjis-win'を与えてもダメでしょうか?
シフトJISのまま「ファイル名」を送っているかもしれません。

投稿2015/10/15 05:57

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Brownie

2015/10/15 06:05 編集

メッセージありがとうございます。 今、試してみましたところ残念ながら string(13) "?????????.txt" という結果でした。 試したコード $result = mb_convert_encoding($_FILES['mail']['name'],'UTF-8','sjis-win'); var_dump($result);
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問