适用场景:电商、CMS、用户头像等图片管理场景。
1接收上传文件
2校验文件(类型、大小、是否真实图片等)
3生成多个尺寸的缩略图
4保存原图和缩略图到指定目录
<?php
class ImageUploader {
private $uploadDir;
private $allowedTypes;
private $maxSize;
private $thumbnailSizes;
private $quality;
public function __construct($config = []) {
$this->uploadDir = isset($config['upload_dir']) ? rtrim($config['upload_dir'], '/') . '/' : './uploads/';
$this->allowedTypes = $config['allowed_types'] ?? ['jpg', 'jpeg', 'png', 'gif'];
$this->maxSize = $config['max_size'] ?? 5242880; // 5MB
$this->thumbnailSizes = $config['thumbnail_sizes'] ?? [
'small' => ['width' => 150, 'height' => 150],
'medium' => ['width' => 300, 'height' => 300],
'large' => ['width' => 600, 'height' => 600]
];
$this->quality = $config['quality'] ?? 90;
}
public function upload($fileKey = 'image') {
if (!isset($_FILES[$fileKey]) || empty($_FILES[$fileKey])) {
return ['success' => false, 'message' => 'No file uploaded'];
}
$file = $_FILES[$fileKey];
$errors = $this->validateFile($file);
if (!empty($errors)) {
return ['success' => false, 'message' => implode(', ', $errors)];
}
if (!$this->createDir($this->uploadDir)) {
return ['success' => false, 'message' => 'Cannot create upload directory'];
}
$ext = $this->getFileExt($file['name']);
$filename = date('YmdHis') . '_' . uniqid() . '.' . $ext;
$originalPath = $this->uploadDir . $filename;
if (!move_uploaded_file($file['tmp_name'], $originalPath)) {
return ['success' => false, 'message' => 'Failed to save file'];
}
$thumbnails = [];
foreach ($this->thumbnailSizes as $name => $size) {
$thumbFile = pathinfo($filename, PATHINFO_FILENAME) . '_' . $name . '.' . $ext;
$thumbPath = $this->uploadDir . $thumbFile;
if (!$this->createThumbnail($originalPath, $thumbPath, $size['width'], $size['height'])) {
return ['success' => false, 'message' => "Failed to create {$name} thumbnail"];
}
$thumbnails[$name] = $thumbPath;
}
return [
'success' => true,
'original' => $originalPath,
'thumbnails' => $thumbnails
];
}
private function validateFile($file) {
$errors = [];
if ($file['error'] !== UPLOAD_ERR_OK) {
$errors[] = 'Upload error: ' . $file['error'];
}
if ($file['size'] > $this->maxSize) {
$errors[] = 'File too large';
}
$ext = $this->getFileExt($file['name']);
if (!in_array($ext, $this->allowedTypes)) {
$errors[] = 'Invalid file type';
}
$info = getimagesize($file['tmp_name']);
if (!$info || !in_array($info[2], [IMAGETYPE_JPEG, IMAGETYPE_PNG, IMAGETYPE_GIF])) {
$errors[] = 'Not a valid image';
}
return $errors;
}
private function createThumbnail($src, $dest, $w, $h) {
$info = getimagesize($src);
if (!$info) return false;
list($sw, $sh, $type) = $info;
$ratio = min($w / $sw, $h / $sh);
$nw = round($sw * $ratio);
$nh = round($sh * $ratio);
$srcImg = $this->createImageFromType($src, $type);
if (!$srcImg) return false;
$dstImg = imagecreatetruecolor($w, $h);
$bg = imagecolorallocate($dstImg, 255, 255, 255);
imagefill($dstImg, 0, 0, $bg);
imagecopyresampled($dstImg, $srcImg, ($w-$nw)/2, ($h-$nh)/2, 0, 0, $nw, $nh, $sw, $sh);
$ext = $this->getFileExt($dest);
$result = $this->saveImageByType($dstImg, $dest, $ext);
imagedestroy($srcImg);
imagedestroy($dstImg);
return $result;
}
private function createImageFromType($path, $type) {
switch ($type) {
case IMAGETYPE_JPEG: return imagecreatefromjpeg($path);
case IMAGETYPE_PNG: return imagecreatefrompng($path);
case IMAGETYPE_GIF: return imagecreatefromgif($path);
default: return false;
}
}
private function saveImageByType($img, $path, $ext) {
switch (strtolower($ext)) {
case 'jpg':
case 'jpeg': return imagejpeg($img, $path, $this->quality);
case 'png': return imagepng($img, $path, (int)(9 - $this->quality / 10));
case 'gif': return imagegif($img, $path);
default: return false;
}
}
private function getFileExt($filename) {
return strtolower(pathinfo($filename, PATHINFO_EXTENSION));
}
private function createDir($dir) {
return is_dir($dir) || mkdir($dir, 0755, true);
}
}
// ===== 调用示例 =====
/*
$config = [
'upload_dir' => './uploads/',
'max_size' => 10 * 1024 * 1024, // 10MB
'thumbnail_sizes' => [
'thumb' => ['width' => 100, 'height' => 100],
'cover' => ['width' => 800, 'height' => 400]
]
];
$uploader = new ImageUploader($config);
$result = $uploader->upload('image'); // 'image' 是表单字段名
if ($result['success']) {
echo "原图: " . $result['original'] . "\n";
foreach ($result['thumbnails'] as $size => $path) {
echo ucfirst($size) . ": " . $path . "\n";
}
} else {
echo "错误: " . $result['message'];
}
*/
?>