PHP入門 リクエスト情報 アップロードの実装($_FILES)

$_FILESは、アップロードしたファイルに関する情報を取得するためのスーパーグローバル変数です。$_FILESを利用することで、ファイルのアップロード機能も直感的に作成できます。

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

例:画像ファイルをサーバーにアップロードする

sample1.php

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>ファイルアップロード</title>
</head>
<body>
<!--アップロード時はenctype属性に注意-->
<form method="POST" action="sample2.php" enctype="multipart/form-data"> //➊
    <label for="upfile">ファイルのパス: </label>
    <input type="hidden" name="max_file_size" value="1000000" />
    <input id="upfile" type="file" name="upfile" size="40" />
    <input type="submit" value="アップロード" />
</form>
</body>
</html>

sample2.php


<?php
// アップロード処理そのものの成否をチェック
if ($_FILES['upfile']['error'] !== UPLOAD_ERR_OK) {
    $msg = [
        UPLOAD_ERR_INI_SIZE => 'php.iniのupload_max_filesize制限を越えています。 ',
        UPLOAD_ERR_FORM_SIZE => 'HTMLのMAX_FILE_SIZE 制限を越えています。',
        UPLOAD_ERR_NO_FILE => 'ファイルはアップロードされませんでした',
        UPLOAD_ERR_NO_TMP_DIR => '一時保存フォルダーが存在しません。',
        UPLOAD_ERR_CANT_WRITE => 'ディスクへの書き込みに失敗しました。',
        UPLOAD_ERR_EXTENSION => '拡張モジュールによってアップロードが中断されました。'
    ];
    $err_msg = $msg[$_FILES['upfile']['error']];
    // 拡張子が許可されたものであるかを判定
} elseif (!in_array(
    strtolower(
        pathinfo($_FILES['upfile']['name'])['extension']),['gif', 'jpg', 'jpeg', 'png'])) {
        $err_msg = '画像以外のファイルはアップロードできません。 ';
// ファイルの内容が画像であるかをチェック
} elseif (!in_array(
    finfo_file(finfo_open(FILEINFO_MIME_TYPE), $_FILES['upfile']['tmp_name']),['image/gif', 'image/jpg', 'image/jpeg', 'image/png'])) { 
        $err_msg='ファイルの内容が画像ではありません。'; 
    //エラーチェックを終えたら、アップロード処理
} else {
    $src = $_FILES['upfile']['tmp_name'];
    $dest = $_FILES['upfile']['name'];
    if (!move_uploaded_file($src, 'doc/'.$dest)) { 
        $err_msg = 'アップロード処理に失敗しました。 ';
    }
}
//エラー発生時はエラーメッセージを表示
if (isset($err_msg)) {
    die('<div style="color: Red;">'.$err_msg. '</div>');
}
// 処理成功時はフォームにリダイレクト (8.4.4項)
header('Location: http://'.$_SERVER['HTTP_HOST'].dirname($_SERVER['PHP_SELF']).'/file1.php');

ファイルを選択ボタンをクリックして、画像ファイルを選択します。アップロードボタンをクリックしてエラーが発生しなければ、ファイルがサーバーにアップロードされます。

実行結果
ファイルを選択ボタンをクリック
ファイルのアップロード
アップロードボタンを押下後

入力フォームの注意点

1、enctype属性を指定する

<form>タグにenctype=”multipart/form-data”を指定する必要があります。enctypeオプションは、フォームデータのエンコード形式を指定するもので、通常はあまり意識する必要がありません。しかし、アップロードに際しては明示的に指定しておかないと、サーバー側で正しくデータを受け取ることができません。

2、ファイル入力ボックスを配置

アップロードファイルの指定には、ファイル入力ボックスとして<input type=”file”>タグを利用します。複数のファイルを同時にアップロードさせたい場合には、複数選択可能なチェックボックスやリストボックスの場合と同様に、要素名にブラケット([])を指定してからmultiple属性を付与します。

<input id="upfile" type="file" name="upfile[]" size="40" multiple />

3、アップロードファイルの上限を設定

name=”max_file_size”の隠しフィールドでは、アップロード可能なファイルサイズの上限を指定できます。

ファイルを複数選択するには、ファイル選択ボックスからCtrlボタンを押しながらファイルを選択します。

アップロード実処理の解説

アップロードファイルの情報を取得するのは、$_FILESの役割です。$_FILESは2次元配列の構造を持っています。

構文:$_FILES

$_FILES['要素名']['情報名']

要素名は、<input type=”file”>タグのname属性で指定された値です。情報名には次の値を指定できます。

スーパーグローバル変数$_FILESで取得可能な情報

情報名概要
nameオリジナルのファイル名
typeアップロードファイルのコンテンツタイプ
sizeアップロードファイルのデータサイズ(バイト)
tmp_nameサーバー上に仮保存されたときの一時ファイル名
error

アップロード時に発生したエラーのコード

定数概要
UPLOAD_ERR_OK0アップロードは成功
UPLOAD_ERR_INI_SIZE1upload_max_filesizeパラメーターの指定サイズを超過
UPLOAD_ERR_FORM_SIZE2HTMLフォームで指定したサイズを超過
UPLOAD_ERR_PARTIAL3ファイルが途中で切れている
UPLOAD_ERR_NO_FILE4ファイルが存在しない
UPLOAD_ERR_NO_TMP_DIR6一時保存のためのフォルダーが存在しない
UPLOAD_ERR_CANT_WRITE7ディスクへの書き込みに失敗した
UPLOAD_ERR_EXTENSION8拡張モジュールによってアップロードが中断された

➊では、name、tmp_nameキーから、それぞれオリジナルのファイル名と一時的なファイルの保存先を取得しています。(PHPでは、クライアントからファイルを受け取ると暫定的に仮のフォルダーに保存しています)あとは、move_uploaded_file関数で一時フォルダーから本来の保存先にファイルを移動するだけです。

構文:move_uploaded_file関数

move_uploaded_file(string $from, string $to) : bool
$from一時ファイルのパス
$to保存先のパス

move_uploaded_file関数は、引数$fromがアップロードされたファイルではなかったり、引数$toに書き込めなかったりした場合などにfalseを返します。この例では、move_uploaded_file関数の戻り値falseであった場合に、変数err_msgにエラーメッセージを設定しています。

複数ファイルのアップロードした場合

複数ファイルのアップロードを有効にした<input type=”file”>要素にmultiple属性を付与した場合、スーパーグローバル変数$_FILESには、以下のような情報がセットされます。

Aarry(
  [upfile]=> Array (
    [name] => Array (
      [0] => test.jpg
      [1] => test.gif
    )
    [type] => Array (
      [0] => image/jpeg
      [1] => image/gif
    )
    ・
    ・
  )

)

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

1、アップロード処理そのものの成否を確認

最初に、$_FILESのerrorキーを確認します。$_FILESにはアップロード時に発生したエラー情報が格納されます

2、アップロードファイルの種類を確認

画像ファイルのみアップロードを許可したい場合は、pathinfo関数を利用してファイルの拡張子を取得します。

構文:pathinfo関数

pathinfo(string $path) : array
$path任意のパス

pathinfo関数は、指定されたパスに関する情報をdirname(親フォルダ)mbasename(ベース名)、extension(拡張子)、filename(ファイル名)などのキーを持った連想配列として返します。

3、画像ファイルであることの確認

finfo_file関数は、与えられたファイル内容を解析してコンテンツタイプを取り出します。

構文:finfo_file関数

finfo_file(resource $finfo,string $filename) : string|false
$finfoFileInfoリソース
$filename対象となるファイル名

FileInfoリソースはfinfo_open関数から生成できます。finfo_file関数から得られたコンテンツタイプを、あらかじめ用意しておいた許可リストと比較し、妥当なファイルかどうかを判定します。

アップロード関連の設定パラメーター

PHPでは、アップロードの挙動を制御するために、php.iniで設定できるさまざまなパラメーターを用意しています。

アップロード関連の設定パラメーター

パラメーター名概要既定値
file_uploadsアップロードを有効にするか1
max_file_uploads同時にアップロードできるファイルの最大数20
upload_max_filesizesアップロード可能な最大サイズ2M
upload_tmp_dirアップロードファイルを一時的に保存するためのフォルダー
post_max_sizeポストデータとして送信可能な最大サイズ8M
memory_limit利用可能なメモリサイズ128M
max_execution_timeスクリプトの最大実行時間(秒)30
max_input_timeスクリプトが入力処理に利用できる最大時間(秒)-1(max_execution_time)