自分は管理画面などのページでよく使い回すので拡張子のチェックを関数にしています。
PHP
1 <?
2 function chk_ext ( $chk_name , $allow_exts = array ( "png" , "pdf" , "jpg" ) ) {
3 //使用出来ない拡張子のチェック
4 $ext_err = true ; //エラーフラグは初期値 真
5 $exts = preg_split ( "/[.]/" , $chk_name ) ; // ファイル名を.で分割する。
6 if ( count ( $exts ) < 2 ) return false ;
7 $ext = $exts [ count ( $exts ) - 1 ] ; //.で分割した最後のブロックの文字列を取得する
8 foreach ( $allow_exts as $val ) {
9 if ( ! empty ( $val ) ) {
10 //$len = strlen( $val );
11 //if( strncasecmp( strtoupper($val), strtoupper($ext), $len ) == 0 ) {
12 if ( strcasecmp ( $val , $ext ) == 0 ) { //修正しました(2016/03/23/01:22)
13 $ext_err = false ; //エラーフラグ 偽に変更
14 break ;
15 }
16 }
17 }
18 $ret = ! $ext_err ; //戻り値はエラーフラグを反転
19 return $ret ;
20 }
21 //ファイル名の拡張子チェックテスト
22 $err_text = "" ;
23 if ( ! chk_ext ( $_FILES [ "upfile" ] [ "name" ] ) ) {
24 $err_text .= "認められていない拡張子です。" ;
25 }
26 ?>
その他にファイルのアップロード時に検証した方が良い項目は以下のようなものがあります。
A. 日本語がファイル名に含まれていないか?
B. ファイル名にA-Za-z_-. 以外の文字が含まれていないか?
C. POST時にエラーが発生していないか?
D. ファイル名が空でないか?
E. 不正なパスを表す文字列がファイル名に含まれていないか?( / や ../ など )
F. ファイルサイズが0バイトより大きく指定値以内か?
G. 本当にアップロードされたファイルなのか?(is_uploaded_file()で確認します)
H. 既存ファイルが存在していないか?(削除して上書きする、またはエラーとするか?)
・A,B,Eについて
POST時にファイル名に指定の英数字と記号以外の文字が含まれていないか及び、
拡張子が存在しているかのチェックをjavascriptで行います。(拡張子のチェックは手抜きでPHPのみです)
HTML
1 <script type="text/javascript">
2 <!--
3 function selOk( ) {
4 var str = document.form1.upfile.value;
5 if( str.match(/[^A-Za-z0-9_\-\.]+/) ) {
6 alert("ファイル名に英数字._-以外の文字が含まれています。");
7 return false;
8 }
9 var ext_i = str.lastIndexOf( ".", str );
10 if( ext_i <= 0 ) {
11 alert("ファイル名に拡張子がありません");
12 return false;
13 }
14 return true;
15 }
16 -->
17 </script>
submitボタンをクリックした時に呼び出してチェックします。
HTML
1 <input name="SubmitFile" type="submit" value="アップロード" onClick="return selOk()">
2
POST後にPHPで同様にチェックします。
PHP
1 <?
2 function is_ansi ( $str ) {
3 //英数字._-だけかチェックします
4 if ( strlen ( $str ) <= 0 ) return false ;
5 if ( preg_match ( "/[^A-Za-z0-9_\.\-]/" , $str ) ) {
6 return false ;
7 } else {
8 return true ;
9 }
10 }
11 //ファイル名のチェック
12 $userfile = basename ( $_FILES [ 'upfile' ] [ 'name' ] ) ;
13 if ( ! is_ansi ( $userfile ) ) {
14 $err_text .= "ファイル名に英数字._-以外の文字列が含まれています。" ;
15 }
16 ?>
17
・Cについて
エラー情報の $_FILES['upfile']['error']の値が0より大きい場合はエラーになります。
・Fについて
$_FILES['upfile']['size']をチェックします。
サーバーのphp.iniの設定が2Mバイトになっているかも確認してみてください。
PHP
1 <?
2 $MAXSIZE = 2097152 ;
3 if ( ( $_FILES [ 'upfile' ] [ 'size' ] > 0 ) && ( $_FILES [ 'upfile' ] [ 'size' ] < $MAXSIZE ) ) {
4 //サイズがOKな場合の処理
5 ?>
move_uploaded_file()のコピー先の指定は安全の為にフルパスで記述するほうが良いかと思います。
纏めるとこんな感じになります。
PHP
1 <?
2 $MAXSIZE = 2097152 ;
3 $save_dir = "/home/sample-net/public_html/images/" ;
4 $info = "" ;
5 $err_text = "" ;
6 if ( ! empty ( $_FILES [ 'upfile' ] [ 'name' ] ) && empty ( $_FILES [ 'upfile' ] [ 'error' ] ) ) {
7 if ( ( $_FILES [ 'upfile' ] [ 'size' ] > 0 ) && ( $_FILES [ 'upfile' ] [ 'size' ] < $MAXSIZE ) ) {
8 if ( is_uploaded_file ( $_FILES [ 'upfile' ] [ 'tmp_name' ] ) ) {
9 //元のファイル名を取得
10 $userfile = basename ( $_FILES [ 'upfile' ] [ 'name' ] ) ;
11 if ( chk_ext ( $userfile ) && is_ansi ( $userfile ) ) {
12 //保存先ファイル名のフルパスを作成
13 $dest_name = $save_dir . $userfile ;
14 $tmpfile = $_FILES [ 'upfile' ] [ 'tmp_name' ] ;
15 if ( ! file_exists ( $dest_name ) ) {
16 //ファイルのコピー処理
17 if ( ! move_uploaded_file ( $tmpfile , $dest_name ) ) {
18 $err_txt .= "ファイルコピーに失敗しました $userfile ... $tmpfile > $dest_name <br>\n" ;
19 } else {
20 $info .= "アップロードに成功しました $userfile ... $dest_name <br>\n" ;
21 chmod ( $dest_name , 0644 ) ;
22 }
23 } else {
24 $err_text .= "既存のファイルです。<br>\n" ;
25 }
26 } else {
27 $err_text .= "ファイル拡張子が認められない形式かファイル名に半角英数字._-以外が含まれています。<br>\n" ;
28 }
29 } else {
30 $err_text .= "ファイルがアップロードされていません。<br>\n" ;
31 }
32 } else {
33 $err_text .= "ファイルサイズが指定サイズ外です。<br>\n" ;
34 }
35 } else {
36 $err_text .= "ファイルアップロードエラーです。<br>\n" ;
37 }
38 ?>
39
40 //formタグの直前あたりにテキストを表示します
41 <?
42 if ( ! empty ( $info ) ) print $info ;
43 if ( ! empty ( $err_text ) ) print $err_text ;
44 ?>
・Hについて
file_exists( )関数で既存ファイルが無いかチェックし、上書きするならunlink()関数を呼びます。
PHP
1 <?
2 if ( file_exists ( $dest_name ) ) {
3 if ( unlink ( $dest_name ) ) {
4 $info .= "既存の同名ファイルを削除しました。<br>\n" ;
5 }
6 }
7 ?>
(これだけ書くとエディタのプレビューが重くなるのは困ったものです。)
動作確認環境 Windows8.1 Pro Firefox 45.0.1
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。