ファイルをアップロード

HTTP通信

ファイルをアップロードするページを作成し、アップロードされたファイルをフォルダーに保存する処理を作ります。
サーバーにアップされたファイルは$_FILEで参照できます。move_uploaded_file()関数を使って練習用に作成しているphpプログラムと同階層に保存します。テキトーな画像も用意しておいてください。

まず単純にファイルをアップロードする画面を作成してみます。

ファイルアップロード処理を行う

<!DOCTYPE html>
<html>
<head>
<title> uploadFile </title>
</head>
<body>
<form method="POST" action="receiveFile.php" enctype="multipart/form-data">
<p>アップするファイル:</p>
<input type="file" name="upload" />
<input type="submit" value="アップロード" />
</body>
</html>

アップロードする画面を作りましたので受け取るプログラムを作成します。

<?php
$tmp = $_FILES['upload']['tmp_name'];//アップロードされたファイルがサーバー上に保存されている一時ファイル名
$file_name = $_FILES['upload']['name'];//クライアントにある元のファイル名
if(!move_uploaded_file($tmp, __DIR__.'/'.$file_name)){
  $err = 'ファイルのアップロードができませんでした。';
}

if(isset($err)){
  die('<div style="color:red;">'.$err.'</div>');
}
header('Location: http://'.$_SERVER['HTTP_HOST'].dirname($_SERVER['SCRIPT_NAME']).'/'.'upFile.php');
?>

upFile.phpを表示すると上のような画面となっておりますので、ファイルを選択をクリックしてテキトーに用意した画像をアップロードしてみましょう。

すると、phpプログラムと同階層にファイルが保存されていることを確認してください。

move_uploaded_file()でアップロードするのですが、第1引数に一時ファイル名、第2引数に保存するパスとファイル名を記述しています。

アップロード時のエラー処理

$_FILESでは、2番目のキー名に’error’を指定すると、アップロード時のエラー内容を取得できます。内容は以下の定数で示されます。

定数内容
UPLOAD_ERR_OK正常処理が行われた
UPLOAD_ERR_INI_SIZEアップロードされたファイルがphp.iniのupload_max_filesizeで
指定された値を超えている。
UPLOAD_ERR_FORM_SIZEアップロードされたファイルがHTMLで指定されたMAX_FILE_SIZEで
指定された値を超えている。
UPLOAD_ERR_PARTIALファイルの一部しかアップロードされませんでした。
UPLOAD_ERR_NO_FILEファイルがアップロードできなかった。
UPLOAD_ERR_NO_TMP_DIR一時保存のためのディレクトリが無い。
UPLOAD_ERR_CANT_WRITEディスクへの書き込みに失敗した。
UPLOAD_ERR_EXTENSIONPHPの拡張モジュールによりアップロードされなかった。

$_FILES[‘file’][‘error’]の値でエラーか正常処理できたか判断できます。

指定したファイル形式以外は拒否する

ファイル形式を指定していないと、悪意のあるファイルをアップロードされた時、大変危険な事態を招く恐れがあります。

pathinfo()で拡張子を取得する

pathinfo()は、第1引数に調べたいパスを記述し、第2引数で返す要素を指定します。

要素内容
PATHINFO_DIRNAMEファイル名を除いたディレクトリパスを取得する。
PATHINFO_BASENAME拡張子を含んだファイル名を取得する。
PATHINFO_FILENAME拡張子を除いたファイル名を取得する。
PATHINFO_EXTENSION拡張子のみ取得する。

上記の第2引数を指定しない場合、全ての要素を連想配列で取得します。

キー名内容
dirnamePATHINFO_DIRNAME
basenamePATHINFO_BASENAME
extensionPATHINFO_FILENAME
filenamePATHINFO_EXTENSION

if文を用いて画像以外のファイルはアップロードできないようにしてみます。

<?php
$ext = pathinfo($_FILEs['upload']['name']);
$allow_ext = array('png','jpg', 'jpeg', 'gif');
if(!in_array(strtolower($ext['extension']), $allow)) {
  $err = '画像をアップロードしてください。';
}
?>

次は実際にアップするデータが本当に画像データであるか調べます。

if(!getimagesize($_FILES['upload']['tmp_name'])){
$err = 'ファイルが画像ではありません。';
}

これらのチェックするプログラムを組み込んで、アップロードされたファイルを処理するプログラムを作成しましょう。

<?php
$ext = pathinfo($_FILES['upload']['name']);
$allow_ext = array('png', 'jpg', 'jpeg', 'gif');

if($_FILES['upload']['error'] !== UPLOAD_ERR_OK){
  $emsg = array(
    UPLOAD_ERR_INI_SIZE => 'ファイルサイズの制限を超えています。',
    UPLOAD_ERR_FORM_SIZE => 'ファイルサイズの制限を超えています。',
    UPLOAD_ERR_PARTIAL => 'ファイルは一部しかアップロードされていません。',
    UPLOAD_ERR_NO_FILE => 'ファイルはアップロードされませんでした。',
    UPLOAD_ERR_NO_TMP_DIR => '一時保存フォルダがありません。',
    UPLOAD_ERR_CANT_WRITE => 'ディスクへの書き込みに失敗しました',
    UPLOAD_ERR_EXTENSION => '拡張モジュールによりアップが中断されました。'
  );
  $err_msg = $msg[$_FILES['upload']['error']];
} elseif (!in_array(strtolower($ext['extension']), $allow_ext)) {
  $err_msg = 'アップロードできるのは画像だけです。';
} elseif (!@getimagesize($_FILES['upload']['tmp_name'])){
  $err_msg = 'ファイルが画像ではありません。';
} else {
  $tmp = $_FILES['upload']['tmp_name'];
  $file_name = $_FILES['upload']['name'];
  if(!move_uploaded_file($tmp, __DIR__.'/'.$file_name)){
    $err_msg = 'ファイルのアップロードができませんでした。';
  }
}
if(isset($err_msg)){
  die('<div style="color:red;">'.$err_msg.'</div>');
}
header('Location: http://'.$_SERVER['HTTP_HOST'].dirname($_SERVER['SCRIPT_NAME']).'/'.'upFile.php');
?>
<!DOCTYPE html>
<html>
<head>
<title> uploadFile </title>
</head>
<body>
<form method="POST" action="receiveFile.php" enctype="multipart/form-data">
<p>アップするファイル:</p>
<input type="hidden" name="max_size" value="1000000" /><!--上限は1M、非表示で指定-->
<input type="file" name="upload" />
<input type="submit" value="アップロード" />
</body>
</html>

上のコードで小さいサイズの画像や1Mより大きい画像、画像じゃないファイルをアップロードして試してください。

コメント

タイトルとURLをコピーしました