画像ファイルのアップロード

(ブログ記事の一覧は「こちら」)

サーバーに画像ファイルを送信(アップロード)する方法を学びましょう。
PHPで用意されている move_uploaded_file 関数を用いると、サーバーにテンポラリファイルをアップロードしてから、指定の場所のファイル名にコピーする、という処理を行っています。

ここで学ぶこと

  • move_uploaded_file 関数
  • $_FILES(スーパーグローバル)

参考:

move_uploaded_file 関数(PHPマニュアル)
exif_imagetype 関数(PHPマニュアル)
pathinfo 関数(PHPマニュアル)
date 関数(PHPマニュアル)

$_FILES について

PHPでは、$_FILES というスーパーグローバル変数が用意されており、POSTでアップロードされたファイルの情報を得ることができます。

以下のフォームでファイルを送信する場合を考えます。

<form action="" method="post" enctype="multipart/form-data">
    <input type="file" name="upload_image">
    <input type="submit" value="送信">
</form>

$_FILES のデータの種類と内容は以下のものがあります。(ファイル入力のinputで指定したnameは「upload_image」)

キー名 記述例 内容
name $_FILES['upload_image']['name'] ファイル名
type $_FILES['upload_image']['type'] ファイルのMIMEタイプ
tmp_name $_FILES['upload_image']['tmp_name'] 一時的に保存されるファイルの名前
error $_FILES['upload_image']['error'] アップロード時のエラーコード
size $_FILES['upload_image']['size'] ファイルサイズ(単位はバイト)

例題1

$_FILES を利用して、画像ファイルのアップロードのプログラムを確認しましょう。

作成するもの

送信ページで画像ファイルを指定して、送信するだけのシンプルなサンプルプログラムです。

プログラム

「htdocs / sample」フォルダに以下のPHPプログラムファイルを用意します。
また、画像ファイルの保存先の「htdocs / sample / image」フォルダも用意します。

以下は送信ページのPHPプログラム「sample_upload_image_send_simple.php」です。

<html>
<head>
   <meta charset="UTF-8">
</head>

<body>
    <h1>シンプルな画像ファイルのアップロード</h1>
    <form action="sample_upload_image_receive_simple.php" method="post" enctype="multipart/form-data">
        <p><input type="file" name="upload_image"></p>
        <p><input type="submit" value="送信"></p>
    </form>
</body>
</html>


続いて、受信ページのPHPプログラム「sample_upload_image_receive_simple.php」です。

<?php
    // 保存するディレクトリ
    $upload_dir = './image/';

    var_dump($_FILES['upload_image']);

    // ファイルの情報
    $name = $_FILES['upload_image']['name'];
    $tmp_name = $_FILES['upload_image']['tmp_name'];

    // ファイルパスからファイル名だけを取得(basename関数)
    $new_name = basename($name);

    // ファイルのアップロード(move_uploaded_file関数)
    move_uploaded_file($tmp_name, $upload_dir . $new_name);
?>

<html>
<head>
   <meta charset="UTF-8">
</head>

<body>
    <h1>受信ページ</h1>
    <div><img src="http://localhost/sample/image/<?php echo $new_name;?>"></div>
</body>
</html>

実行、確認

「sample_upload_image_send_simple.php」を実行して、画像ファイルがサーバーの指定した場所にアップロードされていることを確認してください。

例題2

例題1は、シンプルな画像ファイルのアップロードのプログラムの例でした。しかし、安全に動作させるには十分ではありません。こちらでは以下の対応を追加したプログラムを作成します。

  1. ファイルの種類を制限する
  2. アップロードするファイル名を変更する

プログラム

送信ページのPHPプログラム「sample_upload_image_send.php」です。受信ファイル名以外は同じです。

<html>
<head>
   <meta charset="UTF-8">
</head>

<body>
    <h1>画像ファイルのアップロード</h1>
    <form action="sample_upload_image_receive.php" method="post" enctype="multipart/form-data">
        <p><input type="file" name="upload_image"></p>
        <p><input type="submit" value="送信"></p>
    </form>
</body>
</html>


アップロードするファイル名は、現在の日付/時刻にすることで、同じファイル名が存在しないようにできます。以下のdate関数を使用します。

<?php
    echo date('Ymd_His');

受信ページのPHPプログラム「sample_upload_image_receive.php」です。コメントを参考に、内容を確認してみてください。

<?php
    $err = '';

    // 保存するディレクトリ
    $upload_dir = './image/';

    var_dump($_FILES['upload_image']);

    // ファイルの情報
    $name = $_FILES['upload_image']['name'];
    $tmp_name = $_FILES['upload_image']['tmp_name'];

    // 画像ファイルかどうかを判別(exif_imagetype関数)
    $type = exif_imagetype($tmp_name);
    if ($type == IMAGETYPE_JPEG || $type == IMAGETYPE_PNG) {
        // 拡張子を取得(pathinfo関数)
        $extension = pathinfo($name, PATHINFO_EXTENSION);

        // ファイル名を「年月日_時分秒」にする(date関数)
        $new_name = date('_Ymd_His') . '.' . $extension;

        // ファイルのアップロード(move_uploaded_file関数)
        move_uploaded_file($tmp_name, $upload_dir . $new_name);
    } else {
        $err = '対象ファイルはPNGまたはJPGのみです。';
    }
?>

<html>
<head>
   <meta charset="UTF-8">
</head>

<body>
    <h1>受信ページ</h1>
<?php
    if ($err !== '') {
        echo '<p>' . $err . '</p>';
        echo '<a href="./sample_upload_image_send.php">戻る</a>';
    } else {
?>
    <div><img src="http://localhost/sample/image/<?php echo $new_img;?>"></div>
<?php
    }
?>
</body>
</html>

実行、確認

「sample_upload_image_send.php」を実行して、画像ファイルがサーバーの指定した場所にアップロードされていることを確認してください。また、PNGまたはJPEGフォーマット以外の画像ファイルを指定すると、ファイルがアップロードされないことも確認してください。

課題1

例題2を参考に、アップロードできるファイルサイズを1MB(1024 * 1024 byte)までに制限するプログラムを作成してください。

課題2

move_uploaded_file 関数(PHPマニュアル) を参考に、複数の画像ファイルをアップロードできるように、送信側/受信側のPHPプログラムを修正してください。