PHPで複数ファイルをループ処理して効率的にアップロードする方法

PHPで複数ファイルを一度にアップロードすることは、多くのWebアプリケーションで必要とされる一般的なタスクです。例えば、画像のギャラリーアップロードや大量のドキュメント処理を行うシステムなど、ユーザーにとって一度に複数ファイルを選択してアップロードできる機能は非常に便利です。

本記事では、PHPを使って複数のファイルを一度にアップロードするための基本的な設定やコード実装の方法を段階的に説明します。複数ファイルの処理には$_FILES配列を活用し、ループ処理を行うことで、効率的かつ簡単に実現する方法を学びます。

目次

複数ファイルアップロードの基本概念

PHPで複数ファイルをアップロードする際、通常のシングルファイルアップロードと異なり、$_FILES配列が複数のファイル情報を保持します。この配列には、アップロードされた各ファイルの名前、タイプ、サイズ、エラーステータス、テンポラリディレクトリが含まれます。

PHPは、ユーザーが選択した複数のファイルをこの$_FILES配列に格納し、それらを個別に処理するための情報を提供します。この配列をループで処理することにより、複数ファイルを一度にアップロードすることが可能となります。

複数ファイルアップロードを実現するには、HTMLフォーム側でmultiple属性を使用し、PHP側で配列を正しく処理することが重要です。

HTMLフォームの設定

複数ファイルをアップロードするためには、HTMLフォームの設定が重要です。特に、フォームの<input>タグにmultiple属性を追加することで、ユーザーが複数のファイルを選択できるようになります。

以下は、複数ファイルアップロードに対応した基本的なHTMLフォームの例です。

<form action="upload.php" method="post" enctype="multipart/form-data">
  <label for="files">アップロードするファイルを選択:</label>
  <input type="file" name="files[]" id="files" multiple>
  <input type="submit" value="ファイルをアップロード">
</form>

`multiple`属性の役割

<input type="file">タグにmultiple属性を追加することで、ユーザーは複数のファイルを一度に選択できるようになります。また、name属性にfiles[]と配列形式を指定することで、選択された複数のファイルが$_FILES配列に格納されます。

`enctype=”multipart/form-data”`の設定

フォームタグのenctype属性にmultipart/form-dataを指定することで、ファイルのデータが適切にサーバーに送信されるようになります。この設定がないと、ファイルデータが送信されず、アップロードが正しく機能しません。

この設定により、複数ファイルの選択とアップロードがHTML側で簡単に実現できます。次に、PHP側でこのデータを処理する方法について解説します。

$_FILES配列の処理方法

PHPでは、HTMLフォームでアップロードされたファイルの情報はすべて$_FILESスーパーグローバル変数に格納されます。複数ファイルをアップロードする場合、$_FILESは各ファイルの情報を配列として保持します。$_FILES配列の主なキーには、以下のものがあります。

$_FILESのキー構造

  • name: アップロードされたファイルの名前
  • type: ファイルのMIMEタイプ
  • tmp_name: 一時保存先のファイルパス
  • error: アップロードエラーのステータス
  • size: ファイルサイズ(バイト)

複数ファイルをアップロードする際、これらのキーは配列形式になり、それぞれのファイルに対応する値を保持します。例えば、$_FILES['files']['name']にはアップロードされたファイル名の配列が、$_FILES['files']['tmp_name']には一時保存先のファイルパスの配列が格納されます。

配列の構造例

たとえば、ユーザーが2つのファイルをアップロードした場合、$_FILES配列は次のような形になります。

$_FILES['files'] = [
    'name' => ['file1.jpg', 'file2.png'],
    'type' => ['image/jpeg', 'image/png'],
    'tmp_name' => ['/tmp/phpYzdqkD', '/tmp/phpYx72KJ'],
    'error' => [0, 0],
    'size' => [123456, 234567]
];

重要な点

このように、$_FILESは各ファイルの情報を個別に持つため、ループ処理を利用することで、複数ファイルのアップロードを一度に効率的に処理することが可能です。次のセクションでは、foreachループを使ってこれを実装する方法を紹介します。

foreachループを使用したファイル処理

複数ファイルのアップロードを効率的に処理するためには、PHPのforeachループを使って、$_FILES配列内の各ファイルを個別に処理します。これにより、ユーザーがアップロードした複数のファイルを1つずつ確認し、保存やバリデーションが可能になります。

以下は、$_FILES配列をforeachループで処理する基本的なコード例です。

if (isset($_FILES['files'])) {
    foreach ($_FILES['files']['name'] as $key => $filename) {
        // ファイルが正常にアップロードされたか確認
        if ($_FILES['files']['error'][$key] === UPLOAD_ERR_OK) {
            // 一時ファイルのパス
            $tmp_name = $_FILES['files']['tmp_name'][$key];

            // 保存先ディレクトリを指定
            $destination = 'uploads/' . basename($filename);

            // ファイルを保存
            if (move_uploaded_file($tmp_name, $destination)) {
                echo "ファイル {$filename} がアップロードされました。<br>";
            } else {
                echo "ファイル {$filename} の保存に失敗しました。<br>";
            }
        } else {
            echo "ファイル {$filename} のアップロード中にエラーが発生しました。<br>";
        }
    }
}

各ファイルを処理する手順

  1. $_FILES配列をループで処理
    $_FILES['files']['name']配列のキーを使って、他の情報(tmp_nameerrorなど)にもアクセスし、各ファイルを個別に処理します。
  2. エラーチェック
    $_FILES['files']['error'][$key]を使って、ファイルが正常にアップロードされたかどうかを確認します。エラーがなければ次の処理に進みます。
  3. ファイルの保存
    move_uploaded_file()関数を使用して、アップロードされたファイルを指定したディレクトリに移動します。tmp_nameが一時的なファイルパスであり、destinationは保存先のパスです。

foreachループの利点

  • 複数のファイルを一度に処理できるため、コードがシンプルかつ効率的です。
  • 各ファイルを個別に検証したり、エラーハンドリングを行うことが可能です。
  • 拡張性が高く、後述するバリデーションやエラーハンドリングにも対応しやすい構造です。

次のセクションでは、ファイルの種類やサイズのバリデーションについて詳しく説明します。

ファイルのバリデーション

複数ファイルをアップロードする際には、セキュリティやパフォーマンスの観点から、アップロードされるファイルの種類やサイズをチェックするバリデーションが重要です。これにより、不正なファイルやサイズの大きすぎるファイルがサーバーに保存されることを防ぎます。

ファイルの種類のチェック

アップロードされたファイルのMIMEタイプを確認し、指定されたタイプ以外のファイルを弾くことができます。以下は、画像ファイルのみを許可する例です。

$allowed_types = ['image/jpeg', 'image/png', 'image/gif'];

if (in_array($_FILES['files']['type'][$key], $allowed_types)) {
    // ファイルタイプが許可されている場合の処理
    echo "{$filename} は許可されたファイルタイプです。<br>";
} else {
    echo "{$filename} は許可されていないファイルタイプです。<br>";
}

このコードでは、$allowed_types配列に定義したMIMEタイプ(例:JPEG、PNG、GIF)と、実際のファイルのMIMEタイプを比較します。不正なファイルがアップロードされようとした場合、そのファイルは処理されず、エラーメッセージを表示します。

ファイルサイズのチェック

アップロードされるファイルのサイズを制限することで、大きすぎるファイルのアップロードを防ぐことができます。PHPでは、$_FILES['files']['size'][$key]でファイルサイズをバイト単位で取得できます。

$max_size = 2 * 1024 * 1024; // 2MB

if ($_FILES['files']['size'][$key] <= $max_size) {
    // ファイルサイズが制限内の場合の処理
    echo "{$filename} は許可されたサイズです。<br>";
} else {
    echo "{$filename} はサイズが大きすぎます。<br>";
}

この例では、2MB以下のファイルのみを許可しています。これ以上のサイズのファイルがアップロードされようとした場合、エラーとして処理されます。

バリデーションの組み合わせ

通常、ファイルの種類とサイズを同時にチェックする必要があります。以下は、ファイルの種類とサイズを両方確認し、問題がない場合にのみファイルを処理する例です。

if (in_array($_FILES['files']['type'][$key], $allowed_types) && $_FILES['files']['size'][$key] <= $max_size) {
    // ファイルが許可された種類とサイズの場合に処理を続行
    echo "{$filename} はアップロードできます。<br>";
} else {
    echo "{$filename} はアップロードできません。<br>";
}

エラー時の対応

バリデーションに失敗した場合、適切なエラーメッセージを表示してユーザーに知らせることが重要です。また、エラーハンドリングにより、不正なファイルがサーバーに保存されるのを防ぐことができます。

次のセクションでは、アップロード先ディレクトリの設定とパーミッションについて説明します。

アップロード先ディレクトリの設定

ファイルが正しくアップロードされるためには、保存先のディレクトリが正しく設定され、適切なパーミッションが付与されている必要があります。特に、ファイルをサーバーに保存する際には、ディレクトリの存在確認や書き込み権限を考慮することが重要です。

アップロード先ディレクトリの指定

まず、ファイルを保存するためのディレクトリを指定します。move_uploaded_file()関数を使って、ファイルを一時ディレクトリから目的のディレクトリに移動する必要があります。以下は、uploadsディレクトリにファイルを保存する例です。

$upload_dir = 'uploads/';
$destination = $upload_dir . basename($_FILES['files']['name'][$key]);

if (move_uploaded_file($_FILES['files']['tmp_name'][$key], $destination)) {
    echo "{$filename} が {$upload_dir} にアップロードされました。<br>";
} else {
    echo "{$filename} のアップロードに失敗しました。<br>";
}

ディレクトリの存在確認

ファイルを保存する前に、指定されたディレクトリが存在しているか確認することが重要です。ディレクトリが存在しない場合、アップロードが失敗します。以下は、ディレクトリの存在を確認し、存在しない場合は作成するコードです。

if (!is_dir($upload_dir)) {
    mkdir($upload_dir, 0755, true); // ディレクトリを作成(パーミッション 0755)
}

このコードでは、is_dir()でディレクトリの存在を確認し、存在しない場合はmkdir()で作成します。0755はディレクトリに与えるパーミッションで、所有者に読み書き実行権限、その他のユーザーに読み実行権限を与えています。

ディレクトリのパーミッション設定

ディレクトリには、ファイルを書き込むための適切なパーミッションが必要です。通常、ウェブサーバーが書き込みできるように755775のパーミッションを設定します。これを確認するには、次のようにコマンドラインで確認・変更します。

chmod 755 uploads/

パーミッションが適切でない場合、PHPがファイルを保存できず、エラーが発生します。特に共有ホスティング環境では、この設定に注意が必要です。

セキュリティの考慮

アップロード先ディレクトリには、ウェブ上から直接アクセスされないように注意が必要です。悪意のあるファイルがアップロードされてしまう可能性があるため、特にセキュリティ対策が求められます。たとえば、ディレクトリに.htaccessファイルを置いて、ブラウザからのアクセスを防ぐことが推奨されます。

次のセクションでは、実際にファイルを保存するコードの実装例を詳しく解説します。

ファイル保存の実装例

ここでは、前述した手順を組み合わせて、実際に複数のファイルをサーバーに保存するための完全な実装例を紹介します。この例では、HTMLフォームから受け取った複数ファイルをPHPで処理し、バリデーションを行いながらアップロード先ディレクトリに保存します。

完全なPHPコードの例

以下は、ファイルのバリデーション(ファイルの種類とサイズ)、アップロード先ディレクトリの作成、そしてファイルの保存までを含んだ実装例です。

<?php
// アップロード先ディレクトリの設定
$upload_dir = 'uploads/';
$allowed_types = ['image/jpeg', 'image/png', 'image/gif'];
$max_size = 2 * 1024 * 1024; // 2MB

// ディレクトリが存在しない場合は作成
if (!is_dir($upload_dir)) {
    mkdir($upload_dir, 0755, true);
}

// ファイルがアップロードされているか確認
if (isset($_FILES['files'])) {
    foreach ($_FILES['files']['name'] as $key => $filename) {
        // アップロードにエラーがないか確認
        if ($_FILES['files']['error'][$key] === UPLOAD_ERR_OK) {
            // ファイルのバリデーション(種類とサイズ)
            $file_type = $_FILES['files']['type'][$key];
            $file_size = $_FILES['files']['size'][$key];
            if (in_array($file_type, $allowed_types) && $file_size <= $max_size) {
                // 一時ファイルのパス
                $tmp_name = $_FILES['files']['tmp_name'][$key];

                // 保存先パスを設定
                $destination = $upload_dir . basename($filename);

                // ファイルの移動(アップロード)
                if (move_uploaded_file($tmp_name, $destination)) {
                    echo "ファイル {$filename} が正常にアップロードされました。<br>";
                } else {
                    echo "ファイル {$filename} の保存に失敗しました。<br>";
                }
            } else {
                echo "ファイル {$filename} は許可されていない形式またはサイズが大きすぎます。<br>";
            }
        } else {
            echo "ファイル {$filename} のアップロード中にエラーが発生しました。<br>";
        }
    }
} else {
    echo "ファイルが選択されていません。<br>";
}
?>

コードの説明

  1. アップロード先ディレクトリの設定
    uploads/というディレクトリにファイルを保存します。ディレクトリが存在しない場合、自動的に作成します。
  2. バリデーション
    ファイルの種類がimage/jpegimage/pngimage/gifのいずれかであり、かつファイルサイズが2MB以下であることを確認します。
  3. ファイルの移動と保存
    move_uploaded_file()関数を使って、アップロードされたファイルを一時ディレクトリから指定されたuploads/ディレクトリに移動します。移動が成功すれば、アップロード成功メッセージを表示し、失敗すればエラーメッセージを表示します。
  4. エラーハンドリング
    各ファイルに対して、アップロードエラーやバリデーションエラーが発生した場合、適切なエラーメッセージを表示します。

注意点

  • ファイル名の衝突を防ぐために、保存前にファイル名の重複チェックや、ランダムなファイル名への変更などの工夫が必要になる場合があります。
  • アップロードされたファイルが安全であることを確認するために、セキュリティ対策としてファイルの拡張子やMIMEタイプの検証を強化することを検討してください。

このコードは基本的な実装例ですが、これを基にプロジェクトの要件に応じてさらにカスタマイズできます。次のセクションでは、アップロード時のエラーハンドリングについて詳しく説明します。

エラーハンドリング

ファイルアップロード中には、さまざまなエラーが発生する可能性があります。これらのエラーを適切に処理し、ユーザーにわかりやすくエラーメッセージを提供することは、ファイルアップロード機能を信頼性の高いものにするために重要です。PHPの$_FILES['error']には、ファイルごとのエラーステータスが格納されており、これを使ってエラーハンドリングを行います。

$_FILES[‘error’]の意味

$_FILES['error']は、アップロード時に発生したエラーを示す定数です。主なエラーコードとその意味は以下の通りです。

  • UPLOAD_ERR_OK (0): エラーなし(正常にアップロードされた)。
  • UPLOAD_ERR_INI_SIZE (1): php.iniで設定されたアップロードファイルサイズの上限を超えた。
  • UPLOAD_ERR_FORM_SIZE (2): HTMLフォームで指定されたMAX_FILE_SIZEを超えた。
  • UPLOAD_ERR_PARTIAL (3): ファイルが一部しかアップロードされなかった。
  • UPLOAD_ERR_NO_FILE (4): ファイルがアップロードされなかった。
  • UPLOAD_ERR_NO_TMP_DIR (6): 一時フォルダが見つからなかった。
  • UPLOAD_ERR_CANT_WRITE (7): ディスクへの書き込みに失敗した。
  • UPLOAD_ERR_EXTENSION (8): PHPの拡張機能によってファイルアップロードが停止された。

エラーハンドリングの実装

エラーコードに応じて適切なメッセージを表示し、ユーザーが原因を理解できるようにします。以下は、エラーコードごとにメッセージを出力する実装例です。

foreach ($_FILES['files']['error'] as $key => $error) {
    if ($error === UPLOAD_ERR_OK) {
        // ファイルが正常にアップロードされた場合
        echo "ファイル {$_FILES['files']['name'][$key]} が正常にアップロードされました。<br>";
    } else {
        // エラーコードに応じてメッセージを出力
        switch ($error) {
            case UPLOAD_ERR_INI_SIZE:
            case UPLOAD_ERR_FORM_SIZE:
                echo "ファイル {$_FILES['files']['name'][$key]} はサイズが大きすぎます。<br>";
                break;
            case UPLOAD_ERR_PARTIAL:
                echo "ファイル {$_FILES['files']['name'][$key]} は部分的にしかアップロードされませんでした。<br>";
                break;
            case UPLOAD_ERR_NO_FILE:
                echo "ファイル {$_FILES['files']['name'][$key]} はアップロードされませんでした。<br>";
                break;
            case UPLOAD_ERR_NO_TMP_DIR:
                echo "一時フォルダが見つかりませんでした。<br>";
                break;
            case UPLOAD_ERR_CANT_WRITE:
                echo "ファイル {$_FILES['files']['name'][$key]} のディスクへの書き込みに失敗しました。<br>";
                break;
            case UPLOAD_ERR_EXTENSION:
                echo "拡張機能によってファイル {$_FILES['files']['name'][$key]} のアップロードが停止されました。<br>";
                break;
            default:
                echo "ファイル {$_FILES['files']['name'][$key]} のアップロード中に不明なエラーが発生しました。<br>";
                break;
        }
    }
}

エラーメッセージのカスタマイズ

ユーザーに対してわかりやすく、具体的なエラーメッセージを提供するためには、メッセージの内容をカスタマイズすることが重要です。例えば、アップロード制限サイズを明記したり、サポートへの連絡方法を示すことで、ユーザーが問題に対応しやすくなります。

echo "ファイル {$_FILES['files']['name'][$key]} はサイズが大きすぎます。最大許可サイズは2MBです。<br>";

ログの記録

特にサーバー運用では、ユーザーにエラーメッセージを表示するだけでなく、エラーをログに記録することも重要です。エラーメッセージをファイルに記録することで、運用上の問題を分析しやすくなります。

error_log("ファイル {$_FILES['files']['name'][$key]} のアップロード中にエラーが発生: エラーコード {$error}", 3, 'upload_errors.log');

このコードは、エラーメッセージをupload_errors.logファイルに記録します。

アップロードエラーの対策

  • サイズエラー対策: php.iniやフォームの設定で、ファイルサイズの上限を適切に設定し、サイズエラーが発生しないようにします。
  • 一時フォルダの設定: サーバー環境で一時フォルダが正しく設定されているか確認し、UPLOAD_ERR_NO_TMP_DIRエラーを防ぎます。
  • 書き込みエラー対策: アップロード先ディレクトリのパーミッションを正しく設定して、UPLOAD_ERR_CANT_WRITEエラーを防ぎます。

次のセクションでは、ファイルのアップロードが成功したかどうかを確認する方法について解説します。

ファイルアップロードの成功確認

ファイルのアップロードが成功したかどうかを確認することは、ユーザーに正しいフィードバックを提供するために非常に重要です。アップロードが成功した場合、適切なメッセージを表示し、失敗した場合にはエラーメッセージを表示する必要があります。

PHPでは、move_uploaded_file()関数がファイルの移動に成功したかどうかを確認できるため、これを活用してアップロードの成功を確認します。さらに、アップロードされたファイルが実際に保存されているかどうかも確認する手法について説明します。

アップロード成功時のメッセージ表示

move_uploaded_file()trueを返す場合、ファイルのアップロードが成功したことを示します。これを利用して、成功時のメッセージを表示するコード例を以下に示します。

if (move_uploaded_file($_FILES['files']['tmp_name'][$key], $destination)) {
    echo "ファイル {$filename} が正常にアップロードされました。<br>";
} else {
    echo "ファイル {$filename} のアップロードに失敗しました。<br>";
}

このコードでは、move_uploaded_file()が成功した場合に、アップロードされたファイル名とともに成功メッセージを表示しています。

アップロード成功確認のポイント

アップロードが成功したことを確認するためのポイントは以下の通りです。

  1. ファイルの存在確認
    move_uploaded_file()が成功しても、サーバー上にファイルが実際に存在しているか確認することが大切です。file_exists()関数を使用して、ファイルが正しく保存されているかチェックできます。
   if (file_exists($destination)) {
       echo "ファイル {$filename} は正しく保存されました。<br>";
   } else {
       echo "ファイル {$filename} が見つかりません。アップロードが失敗しました。<br>";
   }
  1. ファイルサイズの確認
    アップロードされたファイルが完全であることを確認するため、保存されたファイルのサイズを確認するのも有効です。filesize()関数を使って、実際のファイルサイズと、$_FILES['size']のサイズが一致しているか確認します。
   if (filesize($destination) === $_FILES['files']['size'][$key]) {
       echo "ファイル {$filename} は正しくアップロードされ、サイズも一致しています。<br>";
   } else {
       echo "ファイル {$filename} のサイズが不一致です。アップロードに問題が発生しました。<br>";
   }
  1. アップロード後の確認ページ
    複数ファイルをアップロードする場合、すべてのファイルが正常にアップロードされたかをユーザーに確認させるため、アップロードされたファイルの一覧を表示するページを用意することも良い手法です。
   echo "<h3>アップロードされたファイル:</h3>";
   foreach ($_FILES['files']['name'] as $filename) {
       echo "<p>{$filename}</p>";
   }

ユーザーにフィードバックを提供する

ユーザーに対して、アップロードが成功したかどうかを明確に示すことで、より良いユーザーエクスペリエンスを提供できます。たとえば、成功メッセージを強調するために、HTMLやCSSを使って視覚的に区別することも可能です。

<div style="color: green;">
  ファイルが正常にアップロードされました。
</div>
<div style="color: red;">
  ファイルのアップロードに失敗しました。もう一度試してください。
</div>

サーバー側の確認

サーバー管理者としても、アップロードが成功したファイルを確認するために、ログファイルやファイル一覧を定期的にチェックすることが推奨されます。サーバー上に問題が発生した場合、エラーログを確認して原因を特定します。

次のセクションでは、応用例として、複数のフォルダにファイルを分割してアップロードする方法を解説します。

応用:複数フォルダへの分割アップロード

ファイルアップロードの基本的な処理が理解できたら、次のステップとして応用的な処理を考えてみましょう。その一つとして、アップロードされたファイルを複数のフォルダに分割して保存する方法があります。これは、ファイル数が多い場合や、特定の条件に応じてファイルを分類・整理する必要がある場合に有効です。

例えば、以下のようなケースでフォルダ分割アップロードが役立ちます。

  • ファイルタイプごとにフォルダを分ける(画像、ドキュメントなど)
  • 日付ごとにフォルダを作成して整理する
  • ユーザーごとにアップロード先を分ける

ファイルタイプごとにフォルダを分ける

まずは、ファイルの種類(MIMEタイプ)に応じて保存先フォルダを分ける例を紹介します。例えば、画像ファイルはimages/フォルダ、ドキュメントファイルはdocuments/フォルダに保存するといったケースです。

$upload_dir_images = 'uploads/images/';
$upload_dir_docs = 'uploads/documents/';
$allowed_image_types = ['image/jpeg', 'image/png', 'image/gif'];
$allowed_doc_types = ['application/pdf', 'application/msword'];

if (isset($_FILES['files'])) {
    foreach ($_FILES['files']['name'] as $key => $filename) {
        $file_type = $_FILES['files']['type'][$key];
        $tmp_name = $_FILES['files']['tmp_name'][$key];

        // ファイルタイプに応じた保存先フォルダを設定
        if (in_array($file_type, $allowed_image_types)) {
            $destination = $upload_dir_images . basename($filename);
        } elseif (in_array($file_type, $allowed_doc_types)) {
            $destination = $upload_dir_docs . basename($filename);
        } else {
            echo "ファイル {$filename} はサポートされていない形式です。<br>";
            continue;
        }

        // フォルダが存在しない場合は作成
        $destination_dir = dirname($destination);
        if (!is_dir($destination_dir)) {
            mkdir($destination_dir, 0755, true);
        }

        // ファイルを保存
        if (move_uploaded_file($tmp_name, $destination)) {
            echo "ファイル {$filename} が {$destination_dir} にアップロードされました。<br>";
        } else {
            echo "ファイル {$filename} のアップロードに失敗しました。<br>";
        }
    }
}

ポイント

  • フォルダ分け: MIMEタイプに基づき、画像ファイルはuploads/images/に、ドキュメントはuploads/documents/に保存します。
  • フォルダ作成: フォルダが存在しない場合、mkdir()を使用して自動的に作成します。

日付ごとにフォルダを作成して保存

次に、アップロード日ごとにファイルを整理する方法です。この方法は、ファイルが日々増加するシステムにおいて、管理を容易にするためによく使われます。

$upload_base_dir = 'uploads/';
$today = date('Y-m-d'); // 例: 2024-10-14
$upload_dir = $upload_base_dir . $today . '/';

if (isset($_FILES['files'])) {
    foreach ($_FILES['files']['name'] as $key => $filename) {
        $tmp_name = $_FILES['files']['tmp_name'][$key];

        // フォルダが存在しない場合は作成
        if (!is_dir($upload_dir)) {
            mkdir($upload_dir, 0755, true);
        }

        $destination = $upload_dir . basename($filename);

        // ファイルを保存
        if (move_uploaded_file($tmp_name, $destination)) {
            echo "ファイル {$filename} が {$upload_dir} にアップロードされました。<br>";
        } else {
            echo "ファイル {$filename} のアップロードに失敗しました。<br>";
        }
    }
}

ポイント

  • 日付フォルダ: 毎日新しいフォルダ(例: 2024-10-14/)を作成し、その日にアップロードされたファイルを整理します。これにより、ファイルの管理や検索がしやすくなります。

ユーザーごとにフォルダを分ける

最後に、ユーザーごとにアップロード先フォルダを分ける方法です。この方法は、ユーザーアカウントシステムを持つサイトやサービスでよく使われます。

$upload_base_dir = 'uploads/';
$user_id = 123; // ユーザーID(仮)

$upload_dir = $upload_base_dir . 'user_' . $user_id . '/';

if (isset($_FILES['files'])) {
    foreach ($_FILES['files']['name'] as $key => $filename) {
        $tmp_name = $_FILES['files']['tmp_name'][$key];

        // フォルダが存在しない場合は作成
        if (!is_dir($upload_dir)) {
            mkdir($upload_dir, 0755, true);
        }

        $destination = $upload_dir . basename($filename);

        // ファイルを保存
        if (move_uploaded_file($tmp_name, $destination)) {
            echo "ユーザー {$user_id} のファイル {$filename} が {$upload_dir} にアップロードされました。<br>";
        } else {
            echo "ファイル {$filename} のアップロードに失敗しました。<br>";
        }
    }
}

ポイント

  • ユーザーIDごとの整理: ユーザーIDを含むフォルダにファイルを保存することで、複数のユーザーが同時にファイルをアップロードしても衝突を避けることができます。

応用のメリット

  • 整理のしやすさ: ファイルをタイプや日付、ユーザーごとに分けることで、管理がしやすくなり、サーバー側でもファイルの見つけやすさが向上します。
  • パフォーマンスの向上: 複数のフォルダに分割することで、1つのフォルダに大量のファイルが集中することを防ぎ、ディレクトリのパフォーマンスが低下するのを防ぎます。

これらの手法を使って、より柔軟で効率的なファイルアップロードシステムを構築することができます。次のセクションでは、この記事のまとめを行います。

まとめ

本記事では、PHPを使って複数ファイルを効率的にアップロードする方法を解説しました。基本的な$_FILES配列の処理から、foreachループによるファイル処理、バリデーションやエラーハンドリングの方法まで詳しく説明しました。また、応用例として、ファイルを複数のフォルダに分割して保存する方法を紹介しました。

これらの手法を使うことで、ファイル管理が効率化され、セキュリティとパフォーマンスを向上させることが可能です。実際のプロジェクトに応じて、適切にカスタマイズし、実装することが重要です。

コメント

コメントする

目次