• ベストアンサー

画像のアップロードに関して

お世話になっております。画像をブラウザ上からアップロードし、指定のディレクトリ(その都度mkdir関数によりディレクトリを生成)に保存するスクリプトを組んでおりますが、DBにファイル名(または保存先?)を登録するような内容を考えております。 そこでいくつか質問があり投函させて頂きます。 1・アップロードする際、クライアントのPC内にあるファイル名が日本語だった場合、そのままアップロードさせて問題が発生する事が考えられるか? 2・上記のように日本語である事を想定し、半角英数でリメイクするスクリプトを構築する場合、どのようなリメイクが適当で、どういったスクリプトを記述する事になるか? 3・アップロードさせる際、画像以外をアップロードしないよう規制をかけるにはどうしたら良いか? 4・ディレクトリに画像をアップロードさせる訳だが、後にブラウザ上にその画像を表示させるには、DBへ保存するのは、やはり<img src="…… といったコードを登録する事になるのか? の4点です。スキルが無くここ数日頭を悩ませながら、進んでは振り出しに戻るを繰り返しており、丸投げのつもりは一切無いのですが、ポイントをご指導いただければ幸いに思い、投函させて頂きました。 お手数お掛けいたしますが、ご教授のほど宜しくお願い申し上げます。

質問者が選んだベストアンサー

  • ベストアンサー
  • Ikonos00
  • ベストアンサー率28% (86/302)
回答No.10

>ereg("(^[a-zA-Z0-9_-]+)\.(jpg)|(^[a-zA-Z0-9_-]+)\.(gif)",$_FILES['fl1']['type']) ファイル名を見るので、 $_FILES['fl1']['type']ではなくて$_FILES['fl1']['name']では? 個人的には (1)ereg("(^[a-zA-Z0-9_-]+)\.(jpg)|(^[a-zA-Z0-9_-]+)\.(gif)",$_FILES['fl1']['name']) より (2)eregi("^[a-z0-9_-]+\.(jpg|gif)$",$_FILES['fl1']['name']) の方がすっきりして見やすいかと。 (2)はeregiで大文字小文字の区別をしていませんので、 拡張子が大文字の場合でもマッチします。

sadacha
質問者

お礼

Ikonos00様 こんばんは。ご丁寧なアドバイスを有難う御座います。色々と勉強になります。 今回、質問させて頂いた内容、全て解決したわけではありませんが、流れや考え方など、貴重なアドバイスを頂戴したと有難く思っております。 今回の件につきましても、今後アドバイスを頂戴したく質問(投函)させて頂くかとは思いますが、今後とも宜しくお願い致します。 有難う御座いました。 最後に、今回アドバイスを頂いた皆様へ… アドバイスを頂戴した私から回答者への評価(ポイントにて順位付け)をする事に恐縮し、個人的な気持ちでは皆さんに20ptと思っていることをご理解いただければと思います。 改めまして・・・有難う御座いました。

その他の回答 (9)

  • Ikonos00
  • ベストアンサー率28% (86/302)
回答No.9

一度にいろいろやろうとして混乱しているようですね。 まずは、ひとつひとつの処理の動作確認をして、 1つの画像をアップロードできてから、 3つにチャレンジすることをお勧めします。 とりあえず1つ。 $_FILES['fl1']['name'][$i]って何が入っているのでしょう?

sadacha
質問者

お礼

Ikonos00様 こんばんは。度々のご指導ありがとう御座います。 ちゃんとアップロードできるようになりました。 Ikonos00様も仰っているように、今回の質問の内容を全て解決出来るまでには、もう暫く時間が掛かりそうなので、一旦解決済みとして、改めて分からなくなったときに質問させて頂こうかと思うのですが、最後に以下の内容をご指導頂けないでしょうか?お手数お掛けしますが宜しくお願い致します。 if(!preg_match("/^image\/.*(png|jpeg|gif)$/",$_FILES['fl1']['type']) and $name1<>""){ を使い、画像ファイル以外は弾くように出来たのですが、日本語名のファイルも弾くために、 ereg("(^[a-zA-Z0-9_-]+)\.(jpg)|(^[a-zA-Z0-9_-]+)\.(gif)",$_FILES['fl1']['type']) このようなコードも付け足したいのですが、上手くいかないのです。

  • Ikonos00
  • ベストアンサー率28% (86/302)
回答No.8

>3.$_FILES['element']['type']にMIMEが入ってます。 http://search.net-newbie.com/php/features.file-upload.html $_FILES['element']['type']を使って、ファイルの種類をチェックする場合(イメージ)は、 if(!preg_match("/^image\/.*(png|jpeg|gif)$/",$_FILES['element']['type'])){ echo("png,jpeg,gifではありません。"); } という感じです。 ファイルの拡張子でチェックする場合は、 単純に、ファイル名の最後の"."以降を取り出して、 png(jpg、gif、等)だけアップロードを許可する という書き方をすればよいです。

sadacha
質問者

お礼

Ikonos00様 おはよう御座います。お休みの日、朝早くからのアドバイスを有難う御座います。 これからアドバイスを基に色々と試してみたいと思います。 まずはご挨拶までに…後ほど改めてご報告いたします。有難う御座いました。

sadacha
質問者

補足

補足から失礼します。拡張子によってアップロードを防ぐものは出来たのですが、実際に画像をアップロード出来ずにおります。。 アップロードフォーム?が3つあり、全てnameをfl[]とすれば問題ないのですが、各々表示させたい場所を指定したいため、nameをfl1、fl2...としております。他に良いコードもあるのでしょうが、スキルがないもので…。まだまだ完成には程遠いのですが、この辺りも含めてご指導いただければ幸いです。 <?php $name1 = $_FILES['fl1']['name']; $name2 = $_FILES['fl2']['name']; $name3 = $_FILES['fl3']['name']; if(!preg_match("/^image\/.*(png|jpeg|gif)$/",$_FILES['fl1']['type']) or !preg_match("/^image\/.*(png|jpeg|gif)$/",$_FILES['fl2']['type']) or !preg_match("/^image\/.*(png|jpeg|gif)$/",$_FILES['fl3']['type'])){ echo("png,jpeg,gifではありません。"); exit; } //フォーム上に新規フォルダ名を入力し、フォルダを生成 $nam=$_POST['id']; mkdir ("/home/public_html/upload-test/check/$nam",0755); echo <<<EOD 画像1: {$name1}<br> 画像2: {$name2}<br> 画像3: {$name3}<br> EOD; $num=0; for($i=0;$i<sizeof($_FILES['fl1']['name']);$i++){ if($_FILES['fl1']['name'][$i]==""){continue;} if(file_exists("./check/$nam/".mb_convert_encoding($_FILES['fl1']['name'][$i],"SJIS","EUC-JP"))==TRUE && $_POST['frb']=="true"){ $num++; }elseif(!is_uploaded_file($_FILES['fl1']['tmp_name'][$i])){ $num++; }else{ move_uploaded_file($_FILES['fl1']['tmp_name'][$i],"./check/$nam/".mb_convert_encoding($_FILES['fl1']['name'][$i],"SJIS","EUC-JP")); } } for($i=0;$i<sizeof($_FILES['fl2']['name']);$i++){ if($_FILES['fl2']['name'][$i]==""){continue;} if(file_exists("./check/$nam/".mb_convert_encoding($_FILES['fl2']['name'][$i],"SJIS","EUC-JP"))==TRUE && $_POST['frb']=="true"){ $num++; }elseif(!is_uploaded_file($_FILES['fl2']['tmp_name'][$i])){ $num++; }else{ move_uploaded_file($_FILES['fl2']['tmp_name'][$i],"./check/$nam/".mb_convert_encoding($_FILES['fl2']['name'][$i],"SJIS","EUC-JP")); } } for($i=0;$i<sizeof($_FILES['fl3']['name']);$i++){ if($_FILES['fl3']['name'][$i]==""){continue;} if(file_exists("./check/$nam/".mb_convert_encoding($_FILES['fl3']['name'][$i],"SJIS","EUC-JP"))==TRUE && $_POST['frb']=="true"){ $num++; }elseif(!is_uploaded_file($_FILES['fl3']['tmp_name'][$i])){ $num++; }else{ move_uploaded_file($_FILES['fl3']['tmp_name'][$i],"./check/$nam/".mb_convert_encoding($_FILES['fl3']['name'][$i],"SJIS","EUC-JP")); } } if($num>0){ print("<div style='color:red'>".$num."件がアップロードに失敗しました</div>"); } ?>

  • tany180sx
  • ベストアンサー率63% (239/379)
回答No.7

1.問題があるので日本語はやめた方がいいです。 DBに保存するのが無難かと。 2.SeeSaaブログだとたぶんこんな感じです。 bin2hex(mb_convert_encoding("ファイル名", "SJIS-win")) またはurlencode() 3.$_FILES['element']['type']にMIMEが入ってます。 4.ファイル名だけでいいと思います。

sadacha
質問者

お礼

tany180sx様 はじめまして、こんばんは。 貴重なアドバイスを有難う御座います。 実は、未だ試行錯誤を繰り返しており、現在フォームからファイルデータを渡す際、そのファイルが画像以外のものを弾くといったところで躓いております(汗)。 >3.$_FILES['element']['type']にMIMEが入ってます。 この意味とはどういった事なのですか?もう少し具体的に教えていただければ幸いです。 というのも、No1-2のphp504様、No3のIkonos00様からGetImageSize()関数の事をお教え頂いたにも拘らず、お恥ずかしいながら それをどう処理したら良いかが分からず、ならばと、ereg("(^[a-zA-Z0-9_-]+)\.(jpg)…と記述しては見たものの、jpgやJPGなどの区別も必要だったり(記述が可笑しいのか、拡張子を認識してくれません。)と、思うような結果を得られずにおります。 MIMEに関しても調べてはみたものの、それをどう処理して良いのかが分からなくて…お手数おかけ致します。

noname#18096
noname#18096
回答No.6

sadachaさん、ごめんなさい。 よく考えたらSQLを使う際には、先に紹介した fopen関数, fwrite関数 は不要でした。 これらの関数は「ファイルに書き込むための関数」で、ログファイルをサーバーに作成する場合に用います。 SQLのデータベースに記録する場合は、別の方法で実装することになると思います。 SQLについては、以下のリンク先を参考になさって下さい。 OKWave PHPの参考書 http://okwave.jp/kotaeru.php3?q=2219132&rev=1 いろいろありますが、PHPマニュアルの中にSQLに関する関数が載っているので、参考になるかと思います。 どうやら、各SQL言語によって別々の関数が用意されているようですので、 どのSQLを使うか決めてから、関数を覚えていく必要があると思います。 Webスペースを利用する場合は、サービス概要に「MySQLを使用しています」というような説明がありますので、その方面からも調べてみて下さい。

sadacha
質問者

お礼

aquacent様 こんにちは。ご丁寧にご連絡頂き有難う御座います。 ご紹介いただいたサイトの内容を確認しながら学んでいきたいと思います。 未だ解決せず、またこの場において質問する事もあるかと思いますが、引き続きご指導いただければ幸いです。

noname#18096
noname#18096
回答No.5

> ログを残すですか 例えば、友達との思い出.zip というファイルをアップロードしたとします。 アップロードされた時点で、ファイル名は upload001.zip になりますが、「元ファイル名が 友達との思い出.zip である」という情報をログに書き込んでおけば、 後でログを参照して、ページに元ファイル名を表示させることが出来ます。 > 「アクセスログを記録する」といった題材がありましたが、こちらでもヒントがありますでしょうか。 タイトルから察するに、これはアクセス解析の事ですよね。 ログに保存する点では同じなので、ファイル書き込みの参考にはなると思います。 参考までに、ファイル書き込み時には以下の関数を使います。 PHP: fopen - Manual http://jp2.php.net/manual/ja/function.fopen.php PHP: fwrite - Manual http://jp2.php.net/manual/ja/function.fwrite.php > このプレフィックスとはどういうことでしょうか。 「プレフィックス=接頭語」です。 リネームするときなどに、「プレフィックスを付ける」という言葉を聞いたことがありませんか? upload001.zip の場合は、"upload" が定められた接頭語で、アップロードされれば必ず付与される語句です。 "001" が連番で、その次にアップロードされれば、upload002.zip となります。 "1" ずつ数字が足されていくので、既存のファイル名と重複しないメリットがあります。 > 連番とは、SQLに登録する際のもので、SQLの属性を変更(設定)する事を仰っているのですか? まず初めに。 私はSQLに関しては知識がないので、掘り下げた説明は出来ないことをご承知おきください。 ファイル名に連番を付与する場合は、投稿回数(アップロードされた回数)を覚えておく必要があります。 例えば、投稿回数が3回なら、次に付与する連番は 004 でなければなりません。 最後に投稿された upload003.zip の 3 を覚えておく必要があるわけです。 SQLを使うのでしたら、 "3" という数値をデータベースに記録しておけばよいでしょう。

sadacha
質問者

お礼

aquacent様 早速のお返事、そして参考サイトのご紹介を有難う御座います!早速参考に訪問させて頂きます! 私の質問内容が多かったために、整理出来ないところがありますが、ご指導いただいた方々のアドバイスを下に、順を追って整理しながらまとめて行きますので、後ほど改めてご報告を兼ねて(補足欄にて)ご連絡させて頂きます。引き続きご指導いただければ幸いです。 まずはご挨拶までに…有難う御座いました。

noname#18096
noname#18096
回答No.4

> 1・アップロードする際、クライアントのPC内にあるファイル名が日本語だった場合、そのままアップロードさせて問題が発生する事が考えられるか? ダウンロード時にURLエンコードしたURIを渡せば、問題ないと思います。 ただし、既存のファイル名と重複しないように、重複チェックを行う必要があります。 ファイル名をログに残してチェックするか、opendir関数+readdir関数でディレクトリ内のファイルリストをその都度取得するか。 いずれにしても、あまり効率の良い方法ではないので、お勧めはしません。 アップロード時のファイル名を残したいのなら、ログに残して元ファイル名を表示させる方がスマートだと思います。 > 2・上記のように日本語である事を想定し、半角英数でリメイクするスクリプトを構築する場合、どのようなリメイクが適当で、どういったスクリプトを記述する事になるか? 一般的には、upload001.zip のように「プレフィックス+連番」の書式でファイル名に割り当てされます。 連番を付ければ、既存のファイル名と重複しないので重複チェックする必要がない、というのが理由でしょう。

sadacha
質問者

お礼

aquacent様 はじめまして、こんにちは。貴重なご意見を有難う御座います。 >アップロード時のファイル名を残したいのなら… ログを残すですか…購入した本に「アクセスログを記録する」といった題材がありましたが、こちらでもヒントがありますでしょうか。。今からよく読んでみます。 >一般的には、upload001.zip のように「プレフィックス+連番」の書式でファイル名に割り当てされます。 このプレフィックスとはどういうことでしょうか。今、PHPのマニュアルで検索しましたを今一理解が乏しくて…それと、php504様も仰っていましたが、連番とは、SQLに登録する際のもので、SQLの属性を変更(設定)する事を仰っているのですか? 分からない事ばかりですみません。色々と貴重なアドバイスを頂き、本当皆様には感謝しております。

  • Ikonos00
  • ベストアンサー率28% (86/302)
回答No.3

1.について 安全策として、ファイルアップロードの際に、 名前を変更して保存した方が良いかと思います。 ということで、2.ですね。 2.について 他の画像と重複しない名前をつけます。 例えば日時で、yymmddhhmmss×××。 まあ、これでも重なる可能性はありますが…。 3.について #2さんがおっしゃるように、GetImageSize()を使用したり、 ファイル名の拡張子部分をチェックしてはじいたりします。 4.について 後々、画像を削除することも考えたら、 画像の保存場所までのパスの方が良いかと思います。 その場合、ディレクトリ名とファイル名は別々の方が扱いやすいかもしれません。(まあ、一緒に登録して、後からわけることも出来ます。) その他 確認画面で画像をアップロードしてしまうことについてですが、 おそらく、仕方のないことかと…。 入力画面へ戻る時に、画像削除の処理を入れれば良いかなと思います。 消えちゃいましたが確か前回の投稿で、確認画面のときにアップロードがどうこうと読んだような気がします。

sadacha
質問者

お礼

Ikonos00様 こんにちは。お世話になっております。 php504さんも仰っていたGetImageSize()を使うとは、以下のサイトにようなものですよね。拡張子をチェックするとはどういうことになるのでしょうか?分からない事ばかりですみません。 http://search.net-newbie.com/php/function.getimagesize.html その他、貴重なご意見有難う御座います。まだ解決しておらず、引き続き質問させていただく事になるかと思いますので、今後とも宜しくお願い致します。 追伸:前回の件、お騒がせして申し訳ありませんでした。貴重なご意見を有難う御座います。

  • php504
  • ベストアンサー率42% (926/2160)
回答No.2

>3・アップロードさせる際、画像以外をアップロードしないよう規制をかけるにはどうしたら良いか? 拡張子で判断する方法、PHPのGetImageSize()関数で判断する方法が考えられます。

  • php504
  • ベストアンサー率42% (926/2160)
回答No.1

>1・アップロードする際、クライアントのPC内にあるファイル名が日本語だった場合、そのままアップロードさせて問題が発生する事が考えられるか? 文字コードがShift JISの場合に問題があることは確認しています。 UTF-8やEUC-JPでは大丈夫だと思います。 >2・上記のように日本語である事を想定し、半角英数でリメイクするスクリプトを構築する場合、どのようなリメイクが適当で、どういったスクリプトを記述する事になるか? リメイクというのは名前を付け直すことでしょうか。その場合はリネームといった方が適切です。 方法として他のアップローダで見かけるのは連番で数字をつけたりtime()の数字を使ったりしているようです。 >4・ディレクトリに画像をアップロードさせる訳だが、後にブラウザ上にその画像を表示させるには、DBへ保存するのは、やはり<img src="…… といったコードを登録する事になるのか? htmlで表示するデータだからといってそこまで登録する必要はありません。表示する段階で付け足せばいいだけです。 1.<img srcといったhtml文で登録 2.ファイルのパス名だけ登録 3.ディレクトリ名と、ファイル名を別々に登録 自分なら2番目の方法で場合によっては3番目ですかね。

sadacha
質問者

お礼

php504様 こんにちは。早速のお返事有難う御座います。また、貴重なアドバイスに感謝いたします! >UTF-8やEUC-JPでは大丈夫だと思います。 これはPHPファイルの出力の事を言っておられるのですよね?未だ文字コードの知識が乏しいのですが、PHPファイルにに関してはEUC-JPで保存し、EUC-JPで出力するようphp.intで設定しておりますが、MySQLの設定も関係があるのかな?と思いまして… どれも「なるほど…」と思うものばかりですが、現時点で解決した訳ではないので改めてご報告させていただきます。引き続きご指導いただけたら幸いです。

関連するQ&A