【PHP】ファイルをアップロードするとします。$_FILES['userfile']['type']はアップロードする側のマシン環境に依存するらしいのですが、例えば、GIFファイルをアップロードして、$_FILES['userfile']['type']で取得するMIMEタイプをimage/gif以外にするためには、アップロードする側のマシンでどのような操作をすればよいでしょうか?

回答の条件
  • URL必須
  • 1人2回まで
  • 登録:2009/02/11 20:51:27
  • 終了:2009/02/16 12:42:39

ベストアンサー

id:rouge_2008 No.2

rouge_2008回答回数594ベストアンサー獲得回数3512009/02/13 07:00:52

ポイント60pt

$_FILES['userfile']['type']によるチェックは信用できないそうです。

ファイルの拡張子を変更するだけで、別の形式として認識されてしまいます。

GIFファイルの拡張子を別の物に変更した場合も、「image/gif」以外として認識されます。

$_FILES['userfile']['type']によるチェックしか行っていないのですか?

別のチェックも行っていて、そちらの方ではじいたのではないでしょうか?

拡張子を変更したファイルをアップロードできるか、確認してみてください。

アップロードできない場合は、スクリプトとして安全だと思いますので、そのままで良いと思います。

ユーザーの利便性を考える場合、アップロード不可の理由をメッセージ表示した方が親切だと思いますが、もちろんPHPプログラム側の変更が必要になります。

アップロードできた場合は、別の理由ではじいたことになりますが、ファイルサイズなど別の条件でチェックしていないでしょうか?


http://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q1019135...


※getimagesize()のキー2で、画像の形式を取得できます。

ただし、偽装されたファイルも間違って画像として認識してしまうようです。

http://kikky.net/pc/php_form_file.html

http://nyx.pu1.net/function/image/getimagesize.html

id:tail_furry

$_FILES['userfile']['type']のチェックの前に、$_FILES['userfile']['error']のチェックをかけて、問題がない場合に$_FILES['userfile']['type']のチェックを行うようにしていました。getimagesize()はそのチェックの後の処理で行おうとしていました。

別のチェックではじいた場合にはそこではじいたと判るようにログを取っているため、原因は$_FILES['userfile']['type']だというところまで判っています。

拡張子を変更したファイルは当然アップロードできません。これはデバッグの段階で確認済みでした。

アップロード不可の理由はメッセージ表示していたのですが、ユーザーの方から、正しいファイルをアップしたはずなのになぜファイル形式が違うというメッセージが出るのか、という問い合わせを受けたものですから・・・

ファイルタイプが信用できないというのは今回見直しをしている段階で気づいたのですが、実際にアップロードしてMIMEタイプが変わる場合が再現できなかったため、今回の質問になりました。

コメント欄でのやりとりで解決しましたので、rouge_2008さんにいるかを差し上げます。ポイントも若干多めに配分しました。

2009/02/16 12:41:57

その他の回答(1件)

id:tukihatu No.1

牛乳先生(tukihatu)回答回数180ベストアンサー獲得回数322009/02/12 12:52:22

ポイント20pt

上記の質問の内容はおそらくできないと思います。(アップロードした時のmineタイプを変えるということですよね?)

$_FILES['userfile']['type']がサーバ依存というのは初めて聞きました。自分勉強不足ですね…

いまいちやりたいことが読めないのですが、

GIFをアップロード

GDライブラリ等で任意の画像形式に変更してサーバに保存

読み込み


などで同じことができると思います。

http://www.sakura-pc.jp/php/gd.shtml

GD、pecl、ImageMagickなどをサーバにインストールして、upしたものを参考に新しいファイルを作る手法です。

あと無理やりですが、UPしたデータをテキストで読み、頭のminetypeを書き換えてしまえば、そのファイル形式で読んでくれると思います。おそらく表示はgifのままでしょうけど。

id:tail_furry

それが、実際に事例としてあったために困っているんです…。

プログラム側のMIMEタイプチェック(今回質問した$_FILES['userfile']['type']でのチェックでした)で正常であるはずのファイルをはじいたログが取れてしまったのです。アップロードした側のブラウザがIE7だということまで把握しています。

tukihatuさんのやり方ですと、PHPプログラム側を変更しないといけません。

2009/02/13 00:55:57
id:rouge_2008 No.2

rouge_2008回答回数594ベストアンサー獲得回数3512009/02/13 07:00:52ここでベストアンサー

ポイント60pt

$_FILES['userfile']['type']によるチェックは信用できないそうです。

ファイルの拡張子を変更するだけで、別の形式として認識されてしまいます。

GIFファイルの拡張子を別の物に変更した場合も、「image/gif」以外として認識されます。

$_FILES['userfile']['type']によるチェックしか行っていないのですか?

別のチェックも行っていて、そちらの方ではじいたのではないでしょうか?

拡張子を変更したファイルをアップロードできるか、確認してみてください。

アップロードできない場合は、スクリプトとして安全だと思いますので、そのままで良いと思います。

ユーザーの利便性を考える場合、アップロード不可の理由をメッセージ表示した方が親切だと思いますが、もちろんPHPプログラム側の変更が必要になります。

アップロードできた場合は、別の理由ではじいたことになりますが、ファイルサイズなど別の条件でチェックしていないでしょうか?


http://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q1019135...


※getimagesize()のキー2で、画像の形式を取得できます。

ただし、偽装されたファイルも間違って画像として認識してしまうようです。

http://kikky.net/pc/php_form_file.html

http://nyx.pu1.net/function/image/getimagesize.html

id:tail_furry

$_FILES['userfile']['type']のチェックの前に、$_FILES['userfile']['error']のチェックをかけて、問題がない場合に$_FILES['userfile']['type']のチェックを行うようにしていました。getimagesize()はそのチェックの後の処理で行おうとしていました。

別のチェックではじいた場合にはそこではじいたと判るようにログを取っているため、原因は$_FILES['userfile']['type']だというところまで判っています。

拡張子を変更したファイルは当然アップロードできません。これはデバッグの段階で確認済みでした。

アップロード不可の理由はメッセージ表示していたのですが、ユーザーの方から、正しいファイルをアップしたはずなのになぜファイル形式が違うというメッセージが出るのか、という問い合わせを受けたものですから・・・

ファイルタイプが信用できないというのは今回見直しをしている段階で気づいたのですが、実際にアップロードしてMIMEタイプが変わる場合が再現できなかったため、今回の質問になりました。

コメント欄でのやりとりで解決しましたので、rouge_2008さんにいるかを差し上げます。ポイントも若干多めに配分しました。

2009/02/16 12:41:57
  • id:pahoo
    有効な回答ではないのでコメント欄にて――。

    IE5.0以前、Netscape4.0以前であれば、送信側フォームに

    <input type="file" name="userfile" accept="image/gif" />

    のように accept を記述することで、$_FILES['userfile']['type'] の値を変更することができました。
    残念ながら、現在の大部分のブラウザでは、この方法は利用できません。
  • id:tail_furry
    コメントありがとうございます。
    実際にそのようになるのかテストをしてみたいと思っているので、最近のブラウザでチェックできるような事例ですと嬉しいです。
  • id:pahoo
    ごめんなさい。
    最近のブラウザで accept と同じ効果のある方法があるかどうか、私は知りません。
  • id:rouge_2008
    確認したいこともありますし、2回目なのでコメントで失礼します。

    エラーログにはMIMEタイプも記録されていたのでしょうか?
    MIMEタイプが「image/gif」で記録されている場合は、はじかれた理由は分かりません。
    はじいたファイルのMIMEタイプが確認できない場合は、以下の方法でMIMEタイプを変更してから、PHPプログラムの動作確認をしてみてください。
    ※問題のファイルがGIFではない場合は、拡張子の部分を読み替えてください。

    方法1:レジストリエディタで変更
    1)以下の順番でキーを開いて、目的の拡張子を選択します。
    「HKEY_LOCAL_MACHINE」→「SOFTWARE」→「Classes」→「.gif」

    2)右側の画面の「Content Type」を「image/testgif」など適当な値に変更します。


    方法2:フリーソフトを使用して変更
    「FileTypesMan」を使用しました。
    http://www.forest.impress.co.jp/lib/sys/wincust/customize/filetypesman.html
    1)起動後、一覧が読み込まれたら、目的の拡張子を選択します。

    2)「Edit」→「Edit Selected File Type」を実行

    3)「MIME Type」の欄を編集して適当な値に変更します。

    ※このソフトで変更した場合は、以下の場所に「Content Type」を作成します。
    「HKEY_CURRENT_USER\Software」→「Classes」→「.gif」

    Vistaでは上記の値の方が「HKEY_LOCAL_MACHINE」→「SOFTWARE」→「Classes」→「.gif」より優先されますので、上記「HKEY_CURRENT_USER」のキーに「Content Type」がある場合、「HKEY_LOCAL_MACHINE」の方を変更しても反映されません。
    ※Vistaのみで確認しましたので、XPの挙動は不明です。


    IE7ではMIMEタイプが「image/gif」以外の変更したMIMEタイプで認識されて、正常なGIFファイルのアップロードが拒否されました。
    おそらくIE6でも同様の結果になると思います。
    Firefoxでは影響されませんでした。(アップロード可能)


  • id:tail_furry
    エラーが起こった時点では、ログにMIMEタイプを入れる処理が抜けており、$_FILES['userfile']['type']ではじかれたというログのみです。現在は再度同じ現象が起こった時のためにログにMIMEタイプを入れるようにしています。
    問題が起こったファイルについては、ユーザーの方からいただいてこちらでチェックしてみたのですが、問題はありませんでした。
    はい、問題のファイルはGIFではありません。質問ではあえてGIFにしています。

    レジストリを変更してMIMEタイプを変更しようとするのは実は既に試みています。それはボクの前の質問に関係しています。
    http://q.hatena.ne.jp/1234246081
    レジストリを変更したけどどういうわけかMIMEタイプの関連付けが外れなかったという状況でした。

    フリーソフトを使用して変更するテストはまだ試していませんので、週明けに試してみたいと思います。
    どうもありがとうございます。
  • id:rouge_2008
    問題のファイルは、JPEGまたはPNGでしょうか?
    tail_furryさんの環境では、問題のファイルもIE7でアップロード可能だったのですか?
    MIMEタイプの設定などPCに問題があるのではなく、画像ファイルとIEの仕様が原因の可能性があります。
    JPEGは通常「image/jpeg」とされていますが、実際は「image/pjpeg」である場合が多いようです。
    手持ちのソフト(Paint Shop Pro)とフリーソフト(GimpとPictBearSE)で確認しましたが、いずれも「image/pjpeg」でした。
    ※プログレッシブJPEGが「image/pjpeg」になるというのは間違いのようです。
    通常の非プログレッシブJPEGも「image/pjpeg」と認識されました。

    ※PNGの場合も、「image/png」ではなく「image/x-png」でした。
    ※IEでは上記の問題が起きますが、FirefoxおよびSafariでのアップロード時には、それぞれ「image/jpeg」「image/png」と認識されました。


    この問題はけっこう有名なようです。
    http://d.hatena.ne.jp/hacking_dubby/20050601/1124264267

    http://blog.iwa-ya.net/2006/08/20/185023

    IEで「image/jpeg」と認識されるJPEGファイルの作成方法は不明です。
    上記の記事にもありましたが、PHPプログラムを変更して、「image/pjpeg」および「image/x-png」を追加した方が良いかもしれません。


    ※レジストリおよびフリーソフトによるJPEGのMIMEタイプ変更は有効でした。(きちんと変更が反映されます。)
    変更した値の方が優先されて、「image/pjpeg」以外で認識されました。
    ただし、「image/jpeg」に戻すと「image/pjpeg」として認識されてしまいます。

    PCの設定の問題ではなかった場合は、PHPプログラムを変更するか、あるいはFirefoxなど別のブラウザでアップロードしてもらうしかないと思います。


    ※関連付けについては、今回のことでは変更する必要はないと思います。
    別のソフトに変更した時のMIMEタイプを確認したいという場合は関連付けたいソフトの設定画面から設定してみてはいかがでしょうか?
  • id:tail_furry
    前の質問で書いてしまったのでばらしてしまいますが、問題のファイルはjpegです。
    PHPプログラムでは、image/jpegのほかにimage/pjpegもちゃんとチェックしていました。
  • id:tail_furry
    問題のファイルはIE7でアップロード可能でした。IE6でも試しています。
  • id:tukihatu
    すみません。すごい勘違いしてました。ポイント0にしちゃってください^^;

    >問題が起こったファイルについては、ユーザーの方からいただいてこちらでチェックしてみたのですが、問題はありませんでした。
    >問題のファイルはIE7でアップロード可能でした。IE6でも試しています。
    ユーザ環境では問題が起こるけど、こちら側の環境では無問題、ということですね。

    画像ファイルやブラウザ仕様でないとすると…OSや通信環境、と考えたくなりますね。
    しかし$_FILES['userfile']['error']まで正常に来ているのだから、通信が途中で切れたとかそういう話ではないだろうし…
    vistaのIE7で送信する、だけではなく、サービスパック入り等いろいろな追加条件があるのかもしれません。
    windows mobileの可能性もあるし。

    ユーザの環境をちょっと聞き出して…ができればいいんですけどね。
  • id:rouge_2008
    「image/pjpeg」もチェックしていて、tail_furryさんや他のユーザーさんでは問題が起きていないとなると、やはりそのユーザーさんのPCの問題の可能性が高いですね。
    IEのキャッシュの削除などは試してもらったのでしょうか?
    キャッシュがたまりすぎていると、WEB関係のいろんな所に不具合が出るようです。(IEでBMPしか保存できない・・・など。)

    関連付けに問題があるとしても、単なる設定ミスなら良いのですが・・・
    XPの場合、関連付けを作成し直しても問題が解決しない場合は、リカバリー(あるいは再インストール)しかないかもしれません。
    ログにOSは記録されていないのでしょうか?


    レジストリの各キーの関係について、簡単に調べてみました。

    1.「HKEY_CLASSES_ROOT」→「.jpg」
    ↑↓影響しあう(片方を変更するともう一方も変更されます。また、1を削除すると2も削除されます。ただし、逆の場合はそのまま残ります。)
    2.「HKEY_CURRENT_USER」→「Software」→「Classes」→「.jpg」
    ↓影響しない
    3.「HKEY_LOCAL_MACHINE」→「SOFTWARE」→「Classes」→「.jpg」
    ※2のキーが存在しない時、1のキーと相互に連動します。(各々の変更がそれぞれ反映される)
    ※3のキーは他のアカウントの変更も反映されるので、PC全体の設定のようです。

    ※2のキーは、Vistaにのみあり、XPにはないかもしれません。
    (Vistaでは、関連付けがアカウントごとに設定可能になったため)
    未確認ですが、XPの場合は1と3のキーのみ存在し、各々のキーの関係はVistaと同じだと思います。
    動作確認する時の参考になれば幸いです。

  • id:tail_furry
    rouge_2008さんが提示してくださったフリーソフトで変更したところ、変更後もエラーが起きなかったので、もうちょっと詳しく見てみたところ、image/jpegaとしていたため、image/jpegのpreg_matchで正常と認識されていました。preg_matchに引っかからないような値にしたところ、上手く再現できました。
    レジストリをいじったときも、image/jpegaにしていたため、これも引っかからないような値にしたところ、再現できました。ボクの値の設定ミスもあったみたいです。
    (ただし、前の質問については、原因が不明です…)
    どうもありがとうございました。
  • id:rouge_2008
    前の質問の件は謎ですが、とにかく解決して良かったです。
    ポイント&いるかをありがとうございました。

    参考までに・・・

    if (! preg_match("/^image\/(?:gif|(?:x-)?png|p?jpeg)$/",$filetype)) {
    エラー処理

    例えば、上記のようにすれば「image/jpega」もエラーになります。



    関連付けの件もこちらでは問題ありませんでした。
    1.「HKEY_CLASSES_ROOT」→「.jpg」
    2.「HKEY_CURRENT_USER」→「Software」→「Microsoft」→「Windows」→「CurrentVersion」→「Explorer」→「FileExts」→「.jpg」

    上記の2つのキーを丸ごと削除してから、拡張子JPGのファイルをダブルクリックしてもソフトが起動しません。
    「このファイルを開くには~」というメッセージが表示されます。
    2つのキーの削除は、続けて行ったでしょうか?
    削除後に「表示」→「最新の情報に更新」で確認すると確実です。(レジストリエディタのことです。)
    どちらか片方のキーが残った状態では、関連付けられているソフトが起動しました。

  • id:tail_furry
    確認してみたのですが、
    1.「HKEY_CLASSES_ROOT」→「.jpg」
    2.「HKEY_CURRENT_USER」→「Software」→「Microsoft」→「Windows」→CurrentVersion」→「Explorer」→「FileExts」→「.jpg」
    この二つをレジストリエディタで削除して、最新の情報に更新して消えているのを確認後、jpgファイルをダブルクリックしてみたのですが、やはり「Windows画像とFAXビューア」が起動してしまいます。起動した後に、レジストリの値を見てみると、jpgファイルの関連付けの情報が復元されてしまっています。
    どこかに復元するような設定がされているんでしょうか…
  • id:fuk00346jp
    これでドウダ!><;
    「Windows画像とFAXビューア」有効化・無効化
    http://pc725.cocolog-nifty.com/blog/2007/12/windows_fax_806e.html
  • id:tukihatu
    >jpgファイルの関連付けの情報が復元されてしまっています。
    HKEY_LOCAL_MACHINEにもあるのでそっちからかなぁ…?

    HKEY_LOCAL_MACHINE(HKLM)\SOFTWARE\Classes
    拡張子とアプリケーション識別子
    HKEY_LOCAL_MACHIN(HKLM)\SOFTWARE\Classes\Applications
    プログラムから開くに一覧表示される設定

    HKEY_USERS(HKU)\(ユーザー識別子)\Software\Classes\Applications
    プログラムから開くの参照画面に出てくるアプリの設定
  • id:rouge_2008
    確認できないので分かりませんが・・・
    fuk00346jpさんがご紹介している方法で大丈夫かもしれませんね。
  • id:tail_furry
    fuk00346jpさんの方法を試してみました。
    「Windows画像とFAXビューア」を無効化する動作をするだけ(レジストリから削除しない)だと、確かにjpgファイルをクリックすると何も起きないのですが、それは動作としてはおかしいですよね。(どのアプリケーションで開くか選択する動作になるべきです。)
    無効化→レジストリからJPGを削除、だと、無効化しているにも関わらず、なぜか「Windows画像とFAXビューア」が立ち上がってしまいます。
    レジストリからJPGを削除→無効化、でも、やはり「Windows画像とFAXビューア」が立ち上がりました。
  • id:tail_furry
    tukihatuさんの方法になるともうお手上げかもしれません。。。
  • id:fuk00346jp
    !><!
    id:tukihatuさんの出したレジストリ項目は通常いじる項目のミラーなのです。
    参考URL:
    http://www.higaitaisaku.com/hkeyusers.html
  • id:tukihatu
    USERSはミラーだったのかorz
    fuk00346jpさんありがとう!
    WINは「Windows画像とFAXビューア」が標準で固定されているのかもしれませんね。レジストリ以外のどこかで。

    …そんなばかな。きっとレジストリのどこかにあるんだろうな。

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

絞り込み :
はてなココの「ともだち」を表示します。
回答リクエストを送信したユーザーはいません