<?php
/**
* 例外スタックを配列に変換する関数
*/
function exception_to_array(Exception $e) {
do {
$m[] = $e->getMessage();
} while ($e = $e->getPrevious());
return array_reverse($m);
}
/**
* 例外を生成する関数
*/
function e($message, $previous = null) {
return new RuntimeException($message, 0, $previous);
}
/**
* HTML特殊文字をエスケープする関数
*/
function h($str) {
return htmlspecialchars($str, ENT_QUOTES, 'UTF-8');
}
// 例外変数初期化
$e = null;
if (isset($_FILES['upfile']['error']) && is_array($_FILES['upfile']['error'])) {
try {
// 各ファイルをチェック
foreach ($_FILES['upfile']['error'] as $k => $error) {
try {
// 更に配列がネストしていれば不正とする
if (is_array($error)) {
throw e("[{$k}] パラメータが不正です", $e);
}
// $_FILES['upfile']['error'][$k] の値を確認
switch ($error) {
case UPLOAD_ERR_OK: // OK
break;
case UPLOAD_ERR_NO_FILE: // ファイル未選択
continue 2;
case UPLOAD_ERR_INI_SIZE: // php.ini定義の最大サイズ超過
case UPLOAD_ERR_FORM_SIZE: // フォーム定義の最大サイズ超過
throw e("[{$k}] ファイルサイズが大きすぎます", $e);
default:
throw e("[{$k}] その他のエラーが発生しました", $e);
}
// ここで定義するサイズ上限のオーバーチェック
if ($_FILES['upfile']['size'][$k] > 1000000) {
throw e("[{$k}] ファイルサイズが大きすぎます", $e);
}
// move_uploaded_file関数での「実際にアップロードされたファイルかどうか」
// のチェックを今回は行わないので、is_uploaded_file関数でのチェックが必要
if (!is_uploaded_file($_FILES['upfile']['tmp_name'][$k])) {
throw e("[{$k}] 不正なファイルです", $e);
}
// $_FILES['upfile']['mime']の値はブラウザ側で偽装可能なので
// MIMEタイプに対応する拡張子を自前で取得する
$info = getimagesize($_FILES['upfile']['tmp_name'][$k]);
if ($info === false) {
throw e("[{$k}] 画像ファイルではありません", $e);
}
switch ($info['mime']) {
case 'image/gif':
$mime = $ext = 'gif';
break;
case 'image/png':
$mime = $ext = 'png';
break;
case 'image/jpeg':
$mime = 'jpeg';
$ext = 'jpg';
break;
default:
throw e("[{$k}] 画像形式が未対応です", $e);
}
// 画像処理に使う関数名を決定する
$create = "imagecreatefrom{$mime}";
$output = "image{$mime}";
// 縦横比を維持したまま 120 * 120 以下に収まるサイズを求める
if ($info[0] >= $info[1]) {
$dst_w = 120;
$dst_h = 120 * $info[1] / $info[0];
} else {
$dst_w = 120 * $info[0] / $info[1];
$dst_h = 120;
}
// ファイルデータからSHA-1ハッシュを取ってファイル名を決定する
$src = $create($_FILES['upfile']['tmp_name'][$k]);
$dst = imagecreatetruecolor($dst_w, $dst_h);
imagecopyresampled(
$dst, $src,
0, 0, 0, 0,
$dst_w, $dst_h, $info[0], $info[1]
);
$output(
$dst,
sprintf('./resized/%s.%s',
sha1_file($_FILES['upfile']['tmp_name'][$k]),
$ext
)
);
// リソースを解放
imagedestroy($src);
imagedestroy($dst);
// 形式上、正しい処理を行ったが例外としてスローしておく
throw e("[{$k}] リサイズして保存しました", $e);
} catch (RuntimeException $e) { }
}
} catch (RuntimeException $e) { }
}
// ヘッダー送信
header('Content-Type: text/html; charset=utf-8');
?>
<!DOCTYPE html>
<html lang="ja">
<head>
<title>画像アップロード</title>
</head>
<body>
<?php if ($e): ?>
<ul>
<?php foreach (exception_to_array($e) as $msg): ?>
<li><?=h($msg)?></li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
<form enctype="multipart/form-data" method="post" action="">
<fieldset>
<legend>画像ファイルを選択(JPEG, GIF, PNGのみ対応)</legend>
<ul>
<?php for ($i = 0; $i < 10; $i++): ?>
<li><input type="file" name="upfile[]"></li>
<?php endfor; ?>
</ul>
<input type="submit" value="送信">
</fieldset>
</form>
</body>
</html>
preferences:
34.46 ms | 402 KiB | 5 Q