PHP によるファイルアップロードの例
このページは、PHP で ファイルアップロードを行う例を記載したページです。
注意
- コードのライセンスは CC0 (クレジット表示不要、改変可、商用可) です。
コード
<?php
/**
* ファイルをアップロードします。
*
* @param string $name <input> の name 属性
* @param string $uploadDir アップロードフォルダのパス
* @param array $options {
* オプション配列
*
* @type array $allows 許可するファイルのMIMEタイプの配列 (array('image/gif', 'image/png', 'image/jpeg') 等)
* @type callable $filename_callback ファイル名を生成するための関数 (指定されていない場合はアップロードされたファイル名を使用します)
* }
* @return 'success' (成功した場合 true), 'message' (結果メッセージ), 'files' (ファイルアップロード情報) のキーからなる array
*/
function file_upload($name, $uploadDir, $options = array()) {
$allows = isset($options['allows']) ? $options['allows'] : array(); // 許可するMIMEタイプ
$allowsMap = array_fill_keys($allows, true);
$filenameCallback = isset($options['filename_callback']) ? $options['filename_callback'] : null; // ファイル名生成用コールバック
if (isset($_FILES[$name]['tmp_name'])) {
// 複数アップロードでも単一アップロードでも対応できるようにデータを同じ構造にまとめます。
$files = array();
if (is_array($_FILES[$name]['tmp_name'])) {
for ($i = 0; $i < count($_FILES[$name]['tmp_name']); $i++) {
$file = array();
foreach ($_FILES[$name] as $key => $value) { $file[$key] = $_FILES[$name][$key][$i]; }
$files[] = $file;
}
}
else {
$files[] = $_FILES[$name];
}
foreach ($files as $i => $file) {
// 一時フォルダへのアップロード成功
if ($file['error'] == UPLOAD_ERR_OK) {
// MIMEタイプの確認
$mime = mime_content_type($file['tmp_name']);
if (!isset($allowsMap[$mime])) {
return array('success' => false, 'message' => 'アップロードされた形式のファイルは許可されていません。', 'files' => $files);
}
// ファイル名取得
$filename = '';
if (is_callable($filenameCallback)) $filename = call_user_func($filenameCallback, $file); // ファイル名生成
if (strlen($filename) == 0) { // コールバックでファイル名が得られなければアップロードされたファイル名 (使用できない文字を除去)
$filename = trim(preg_replace('#[\x00-\x20\x7f\\\\/:*?\"<>|]#', '', basename($file['name'])), '.');
}
// ファイル移動
$dest = $uploadDir . DIRECTORY_SEPARATOR . $filename;
$move = @move_uploaded_file($file['tmp_name'], $dest);
if (!$move) return array('success' => false, 'message' => 'アップロードに失敗しました。', 'files' => $files);
$files[$i]['dest'] = $dest; // 関数の呼び出し側で必要になる場合がある可能性に備え、配置先をセットしておきます。
}
// 一時フォルダへのアップロード失敗
else {
switch ($file['error']) {
case UPLOAD_ERR_INI_SIZE:
case UPLOAD_ERR_FORM_SIZE:
return array('success' => false, 'message' => 'アップロードの最大容量を超えています。', 'files' => $files);
default:
return array('success' => false, 'message' => 'アップロードに失敗しました。', 'files' => $files);
}
}
}
// アップロード処理成功
return array('success' => true, 'message' => 'アップロードに成功しました。', 'files' => $files);
}
// tmp_name が無い
else {
return array('success' => false, 'message' => 'アップロードに失敗しました。', 'files' => array());
}
}
/**
* ファイル名を生成します。
* @param array $file 単一のファイル情報
* @return string ファイル名
*/
function file_upload_filename_callback($file) {
// 例として一意(UUID v4)のファイル名を生成します。
$extMap = array('image/gif' => 'gif', 'image/png' => 'png', 'image/jpeg' => 'jpg');
$ext = $extMap[ mime_content_type($file['tmp_name']) ];
return sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x.%s',
mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff),
mt_rand(0, 0x0fff) | 0x4000, mt_rand(0, 0x3fff) | 0x8000,
mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff),
$ext
);
}
$result = null;
// POST されている場合、アップロード処理
if (strtoupper($_SERVER['REQUEST_METHOD']) == 'POST') {
$name = 'file1'; // <input> の name 属性
$uploadDir = dirname(__FILE__) . '/uploads'; // アップロードするフォルダ
$options = array(
'allows' => array('image/gif', 'image/png', 'image/jpeg'), // ファイル形式の制限が必要な場合、許可するファイルのMIMEタイプ。不要な場合コメントアウト
'filename_callback' => 'file_upload_filename_callback' // ファイル名のカスタマイズが必要な場合の処理。不要な場合コメントアウト
);
$result = file_upload($name, $uploadDir, $options);
}
?>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>PHP によるファイルアップロードの例</title>
</head>
<body>
<h1>PHP によるファイルアップロードの例</h1>
<!-- enctype は必ず "multipart/form-data" にしてください。PHPの仕組み上、していない場合はアップロードができません。 -->
<form method="post" enctype="multipart/form-data">
<input type="file" name="file1">
<!-- 複数の場合は下記のようなタグになります。
<input type="file" name="file1[]">
<input type="file" name="file1[]">
-->
<input type="submit" value="送信">
</form>
<?php if ($result) echo($result['message']) ?>
</body>
</html>
結果
※下記は画像のためクリックしても動作しません。