Kotchasan Framework Documentation
การจัดการไฟล์และรูปภาพ
การจัดการไฟล์และรูปภาพ
Kotchasan Framework มีคลาสสำหรับการจัดการไฟล์และรูปภาพที่ครอบคลุมทุกความต้องการ ตั้งแต่การอัปโหลด การจัดการ การประมวลผลรูปภาพ จนถึงการจัดเก็บอย่างปลอดภัย
สารบัญ
- File Class - การจัดการไฟล์และไดเรกทอรี
- UploadedFile Class - การจัดการไฟล์อัปโหลด
- Files Collection - คอลเลกชันไฟล์
- Image Class - การประมวลผลรูปภาพ
- การใช้งานในระบบจริง
- Best Practices
File Class - การจัดการไฟล์และไดเรกทอรี
การจัดการไดเรกทอรี
use Kotchasan\File;
// สร้างไดเรกทอรีอย่างปลอดภัย
$uploadDir = '/var/www/uploads/documents/';
if (File::makeDirectory($uploadDir, 0755)) {
echo "ไดเรกทอรีพร้อมใช้งาน";
} else {
echo "ไม่สามารถสร้างไดเรกทอรีได้";
}
// สร้างโครงสร้างไดเรกทอรีที่ซับซ้อน
$userUploadDir = '/var/www/uploads/users/' . $userId . '/documents/';
$imageUploadDir = '/var/www/uploads/users/' . $userId . '/images/';
$tempDir = '/var/www/temp/' . session_id() . '/';
$directories = [$userUploadDir, $imageUploadDir, $tempDir];
foreach ($directories as $dir) {
if (!File::makeDirectory($dir, 0755)) {
throw new Exception("ไม่สามารถสร้างไดเรกทอรี: {$dir}");
}
}
// คัดลอกไดเรกทอรีทั้งหมด
$sourceTemplate = '/var/www/templates/user_template/';
$userCustomDir = '/var/www/uploads/users/' . $userId . '/custom/';
File::copyDirectory($sourceTemplate, $userCustomDir);
echo "คัดลอกไฟล์ template สำเร็จ";การจัดการไฟล์
// ค้นหาไฟล์ในระบบ
$documentFiles = [];
File::listFiles('/var/www/uploads/documents/', $documentFiles, ['pdf', 'doc', 'docx']);
echo "พบเอกสาร " . count($documentFiles) . " ไฟล์:\n";
foreach ($documentFiles as $file) {
echo "- " . basename($file) . " (" . File::ext($file) . ")\n";
}
// ค้นหาไฟล์รูปภาพ
$imageFiles = [];
File::listFiles('/var/www/uploads/images/', $imageFiles, ['jpg', 'jpeg', 'png', 'gif', 'webp']);
// สร้างรายการไฟล์พร้อมข้อมูลเพิ่มเติม
$fileList = [];
foreach ($imageFiles as $file) {
$fileInfo = [
'path' => $file,
'name' => basename($file),
'extension' => File::ext($file),
'size' => filesize($file),
'modified' => filemtime($file)
];
$fileList[] = $fileInfo;
}
// เรียงลำดับตามวันที่แก้ไข
usort($fileList, function($a, $b) {
return $b['modified'] - $a['modified'];
});การทำความสะอาดไฟล์
// ลบไฟล์ temp ที่เก่า
$tempDir = '/var/www/temp/';
$tempFiles = [];
File::listFiles($tempDir, $tempFiles);
$cutoffTime = time() - (24 60 60); // 24 ชั่วโมงที่แล้ว
foreach ($tempFiles as $file) {
if (filemtime($file) < $cutoffTime) {
unlink($file);
echo "ลบไฟล์ temp: " . basename($file) . "\n";
}
}
// ลบไดเรกทอรีที่ว่าง
$userDirs = glob('/var/www/uploads/users/*', GLOB_ONLYDIR);
foreach ($userDirs as $dir) {
$files = [];
File::listFiles($dir . '/', $files);
if (empty($files)) {
File::removeDirectory($dir . '/', true);
echo "ลบไดเรกทอรีว่าง: " . basename($dir) . "\n";
}
}
// ทำความสะอาดไฟล์ cache
$cacheDir = '/var/www/cache/';
File::removeDirectory($cacheDir, false); // ลบเฉพาะไฟล์ใน dir
echo "ทำความสะอาด cache เสร็จสิ้น";
*/UploadedFile Class - การจัดการไฟล์อัปโหลด
การตรวจสอบไฟล์อัปโหลด
use Kotchasan\Http\UploadedFile;
// สมมติว่าได้ UploadedFile จาก Request
$uploadedFile = $request->getUploadedFiles()['document'] ?? null;
if ($uploadedFile && $uploadedFile->hasUploadFile()) {
// ตรวจสอบข้อผิดพลาด
if ($uploadedFile->hasError()) {
$error = $uploadedFile->getErrorMessage();
throw new Exception("เกิดข้อผิดพลาดในการอัปโหลด: {$error}");
}
// ตรวจสอบขนาดไฟล์
$maxSize = 5; // 1024 1024; // 5MB
if ($uploadedFile->getSize() > $maxSize) {
throw new Exception("ไฟล์มีขนาดใหญ่เกินไป (สูงสุด 5MB)");
}
// ตรวจสอบประเภทไฟล์
$allowedTypes = ['pdf', 'doc', 'docx', 'txt'];
if (!$uploadedFile->validFileExt($allowedTypes)) {
throw new Exception("ประเภทไฟล์ไม่ได้รับอนุญาต (อนุญาตเฉพาะ: " . implode(', ', $allowedTypes) . ")");
}
echo "ไฟล์ผ่านการตรวจสอบเบื้องต้น";
} else {
throw new Exception("ไม่พบไฟล์ที่อัปโหลด");
}การจัดเก็บไฟล์อัปโหลด
use Kotchasan\Database;
// สร้างชื่อไฟล์ที่ปลอดภัย
$originalName = $uploadedFile->getClientFilename();
$cleanName = $uploadedFile->getCleanFilename('_');
$extension = strtolower(pathinfo($cleanName, PATHINFO_EXTENSION));
// สร้างชื่อไฟล์ไม่ซ้ำ
$uniqueName = date('Y-m-d_H-i-s') . '_' . uniqid() . '.' . $extension;
// กำหนดโฟลเดอร์จัดเก็บตามประเภท
$uploadPath = match($extension) {
'pdf', 'doc', 'docx' => '/var/www/uploads/documents/',
'jpg', 'jpeg', 'png', 'gif', 'webp' => '/var/www/uploads/images/',
'mp4', 'avi', 'mov' => '/var/www/uploads/videos/',
default => '/var/www/uploads/others/'
};
// สร้างโครงสร้างไดเรกทอรีตามวันที่
$dateDir = $uploadPath . date('Y/m/');
if (!File::makeDirectory($dateDir, 0755)) {
throw new Exception("ไม่สามารถสร้างไดเรกทอรีจัดเก็บได้");
}
$targetPath = $dateDir . $uniqueName;
try {
// ย้ายไฟล์ไปยังตำแหน่งปลายทาง
$uploadedFile->moveTo($targetPath);
// บันทึกข้อมูลไฟล์ลงฐานข้อมูล
$fileData = [
'original_name' => $originalName,
'stored_name' => $uniqueName,
'file_path' => $targetPath,
'file_size' => $uploadedFile->getSize(),
'mime_type' => $uploadedFile->getClientMediaType(),
'extension' => $extension,
'uploaded_at' => date('Y-m-d H:i:s'),
'user_id' => $_SESSION['user_id'] ?? null
];
Kotchasan\Database::create()
->insert('uploaded_files')
->values($fileData)
->execute();
echo "อัปโหลดไฟล์สำเร็จ: {$uniqueName}";
} catch (Exception $e) {
throw new Exception("ไม่สามารถจัดเก็บไฟล์ได้: " . $e->getMessage());
}การสำรองและคัดลอกไฟล์
// สำรองไฟล์สำคัญ
$backupDir = '/var/www/backups/' . date('Y-m-d') . '/';
File::makeDirectory($backupDir, 0755);
try {
// คัดลอกแทนการย้าย (เก็บไฟล์ต้นฉบับ)
$backupPath = $backupDir . $uniqueName;
$uploadedFile->copyTo($backupPath);
// จากนั้นจึงย้ายไปยังตำแหน่งหลัก
$uploadedFile->moveTo($targetPath);
echo "จัดเก็บไฟล์พร้อมสำรองสำเร็จ";
} catch (Exception $e) {
throw new Exception("เกิดข้อผิดพลาดในการจัดเก็บ: " . $e->getMessage());
}Files Collection - คอลเลกชันไฟล์
การจัดการไฟล์หลายไฟล์
use Kotchasan\Files;
// สร้าง Files collection
$files = new Files();
// เพิ่มไฟล์จาก $_FILES
if (isset($_FILES['documents'])) {
if (is_array($_FILES['documents']['name'])) {
// Multiple files
for ($i = 0; $i < count($_FILES['documents']['name']); $i++) {
$files->add(
'document_' . $i,
$_FILES['documents']['tmp_name'][$i],
$_FILES['documents']['name'][$i],
$_FILES['documents']['type'][$i],
$_FILES['documents']['size'][$i],
$_FILES['documents']['error'][$i]
);
}
} else {
// Single file
$files->add(
'document',
$_FILES['documents']['tmp_name'],
$_FILES['documents']['name'],
$_FILES['documents']['type'],
$_FILES['documents']['size'],
$_FILES['documents']['error']
);
}
}
// ประมวลผลไฟล์ทั้งหมด
$uploadResults = [];
$uploadErrors = [];
foreach ($files as $key => $uploadedFile) {
try {
// ตรวจสอบไฟล์
if (!$uploadedFile->hasUploadFile()) {
continue; // ข้ามไฟล์ที่ไม่มี
}
if ($uploadedFile->hasError()) {
$uploadErrors[] = $key . ': ' . $uploadedFile->getErrorMessage();
continue;
}
// ตรวจสอบประเภทไฟล์
$allowedExts = ['pdf', 'doc', 'docx', 'jpg', 'jpeg', 'png'];
if (!$uploadedFile->validFileExt($allowedExts)) {
$uploadErrors[] = $key . ': ประเภทไฟล์ไม่ได้รับอนุญาต';
continue;
}
// อัปโหลดไฟล์
$result = $this->processFileUpload($uploadedFile);
$uploadResults[] = $result;
} catch (Exception $e) {
$uploadErrors[] = $key . ': ' . $e->getMessage();
}
}
// แสดงผลลัพธ์
if (!empty($uploadResults)) {
echo "อัปโหลดสำเร็จ " . count($uploadResults) . " ไฟล์\n";
}
if (!empty($uploadErrors)) {
echo "เกิดข้อผิดพลาด:\n";
foreach ($uploadErrors as $error) {
echo "- {$error}\n";
}
}Image Class - การประมวลผลรูปภาพ
การปรับขนาดรูปภาพ
use Kotchasan\Image;
// ตั้งค่าคุณภาพรูปภาพ
$quality = 8; // 5; // สำหรับ JPEG และ WebP
// ปรับขนาดรูปภาพอัตโนมัติ (รักษาสัดส่วน)
$sourceImage = '/var/www/uploads/original/photo.jpg';
$thumbnailDir = '/var/www/uploads/thumbnails/';
// สร้าง thumbnail ขนาดต่างๆ
$thumbnailSizes = [
'small' => 150,
'medium' => 300,
'large' => 600
];
foreach ($thumbnailSizes as $size => $width) {
$targetFile = $thumbnailDir . $size . '_photo.jpg';
if (Image::resize($sourceImage, $thumbnailDir, $size . '_photo.jpg', $width)) {
echo "สร้าง thumbnail {$size} ({$width}px) สำเร็จ\n";
}
}
// ปรับขนาดพร้อมกำหนดความสูง
$profileDir = '/var/www/uploads/profiles/';
$profileImage = $profileDir . 'profile.jpg';
// สร้างรูปโปรไฟล์ขนาด 200x200 (crop กลาง)
if (Image::crop($sourceImage, $profileImage, 200, 200, '', false)) {
echo "สร้างรูปโปรไฟล์สำเร็จ\n";
}
// สร้างรูป banner แบบ fit (ไม่ crop)
$bannerImage = $profileDir . 'banner.jpg';
if (Image::crop($sourceImage, $bannerImage, 800, 200, '', true)) {
echo "สร้างรูป banner สำเร็จ\n";
}การเพิ่ม Watermark
// ตั้งค่า font สำหรับ watermark
Image::$fontPath = '/var/www/fonts/arial.ttf';
// เพิ่ม watermark ลงในรูปภาพ
$watermarkText = '© 2024 My Website';
// ปรับขนาดพร้อม watermark
$watermarkedFile = '/var/www/uploads/watermarked/photo_wm.jpg';
if (Image::resize($sourceImage, '/var/www/uploads/watermarked/', 'photo_wm.jpg', 800, $watermarkText)) {
echo "เพิ่ม watermark สำเร็จ\n";
}
// Crop พร้อม watermark
$thumbnailWm = '/var/www/uploads/thumbnails/thumb_wm.jpg';
if (Image::crop($sourceImage, $thumbnailWm, 300, 300, $watermarkText, false)) {
echo "สร้าง thumbnail พร้อม watermark สำเร็จ\n";
}การประมวลผลรูปภาพขั้นสูง
// โหลดรูปภาพจาก Base64
$base64Data = 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABgAAD...';
$allowedFormats = ['jpg', 'jpeg', 'png', 'gif', 'webp'];
$imageInfo = Image::loadImageFromBase64($base64Data, $allowedFormats);
if ($imageInfo !== false) {
$imageResource = $imageInfo['resource'];
$mimeType = $imageInfo['mime'];
$extension = $imageInfo['extension'];
// ประมวลผลรูปภาพ
$processedImage = Image::processImageResource($imageResource, 400, 300, 'Sample Watermark', true);
// บันทึกรูปภาพ
$outputFile = '/var/www/uploads/processed/image.' . $extension;
if (Image::saveImageResource($processedImage, $outputFile)) {
echo "ประมวลผลรูปภาพจาก Base64 สำเร็จ\n";
}
// ทำลาย resource
imagedestroy($processedImage);
imagedestroy($imageResource);
}
// ประมวลผลรูปภาพแบบ batch
$sourceDir = '/var/www/uploads/originals/';
$outputDir = '/var/www/uploads/processed/';
$imageFiles = [];
File::listFiles($sourceDir, $imageFiles, ['jpg', 'jpeg', 'png']);
foreach ($imageFiles as $imagePath) {
$filename = basename($imagePath);
$outputPath = $outputDir . $filename;
try {
// โหลดรูปภาพ
$imageResource = Image::loadImageResource($imagePath);
// ปรับขนาดเป็น 800px (รักษาสัดส่วน)
$processedImage = Image::processImageResource($imageResource, 800, 0, '© My Company', false);
// บันทึก
Image::saveImageResource($processedImage, $outputPath);
// ทำลาย resource
imagedestroy($processedImage);
imagedestroy($imageResource);
echo "ประมวลผล {$filename} สำเร็จ\n";
} catch (Exception $e) {
echo "ไม่สามารถประมวลผล {$filename}: " . $e->getMessage() . "\n";
}
}การใช้งานในระบบจริง
ระบบอัปโหลดไฟล์สมบูรณ์
use Kotchasan\Database;
class FileUploadManager
{
private $uploadConfig = [
'documents' => [
'path' => '/var/www/uploads/documents/',
'allowed_exts' => ['pdf', 'doc', 'docx', 'txt'],
'max_size' => 10 1024 1024, // 10MB
'watermark' => false
],
'images' => [
'path' => '/var/www/uploads/images/',
'allowed_exts' => ['jpg', 'jpeg', 'png', 'gif', 'webp'],
'max_size' => 5 1024 1024, // 5MB
'watermark' => true,
'thumbnails' => [150, 300, 600]
],
'videos' => [
'path' => '/var/www/uploads/videos/',
'allowed_exts' => ['mp4', 'avi', 'mov'],
'max_size' => 100 1024 1024, // 100MB
'watermark' => false
]
];
public function handleUpload($uploadedFile, $category, $userId)
{
if (!isset($this->uploadConfig[$category])) {
throw new Exception("ประเภทไฟล์ไม่ได้รับอนุญาต: {$category}");
}
$config = $this->uploadConfig[$category];
// ตรวจสอบไฟล์
$this->validateFile($uploadedFile, $config);
// เตรียมเส้นทางจัดเก็บ
$storagePath = $this->prepareStoragePath($config['path'], $userId);
// สร้างชื่อไฟล์
$fileName = $this->generateFileName($uploadedFile);
$fullPath = $storagePath . $fileName;
// อัปโหลดไฟล์
$uploadedFile->moveTo($fullPath);
// ประมวลผลเพิ่มเติม
$result = $this->postProcessFile($fullPath, $config, $uploadedFile);
// บันทึกลงฐานข้อมูล
return $this->saveFileRecord($result, $category, $userId);
}
private function validateFile($uploadedFile, $config)
{
if (!$uploadedFile->hasUploadFile()) {
throw new Exception("ไม่พบไฟล์ที่อัปโหลด");
}
if ($uploadedFile->hasError()) {
throw new Exception("เกิดข้อผิดพลาด: " . $uploadedFile->getErrorMessage());
}
if ($uploadedFile->getSize() > $config['max_size']) {
$maxSizeMB = $config['max_size'] / (1024 * 1024);
throw new Exception("ไฟล์มีขนาดใหญ่เกินไป (สูงสุด {$maxSizeMB}MB)");
}
if (!$uploadedFile->validFileExt($config['allowed_exts'])) {
throw new Exception("ประเภทไฟล์ไม่ได้รับอนุญาต");
}
}
private function prepareStoragePath($basePath, $userId)
{
$datePath = date('Y/m/d/');
$userPath = $basePath . $userId . '/' . $datePath;
if (!File::makeDirectory($userPath, 0755)) {
throw new Exception("ไม่สามารถสร้างไดเรกทอรีจัดเก็บได้");
}
return $userPath;
}
private function generateFileName($uploadedFile)
{
$originalName = $uploadedFile->getClientFilename();
$cleanName = $uploadedFile->getCleanFilename('_');
$extension = strtolower(pathinfo($cleanName, PATHINFO_EXTENSION));
return date('Y-m-d_H-i-s') . '_' . uniqid() . '.' . $extension;
}
private function postProcessFile($filePath, $config, $uploadedFile)
{
$result = [
'original_path' => $filePath,
'file_size' => filesize($filePath)
];
// ประมวลผลรูปภาพ
if (in_array(File::ext($filePath), ['jpg', 'jpeg', 'png', 'gif', 'webp'])) {
$result = array_merge($result, $this->processImage($filePath, $config));
}
return $result;
}
private function processImage($imagePath, $config)
{
$result = ['thumbnails' => []];
$baseDir = dirname($imagePath) . '/';
$baseName = pathinfo($imagePath, PATHINFO_FILENAME);
$extension = pathinfo($imagePath, PATHINFO_EXTENSION);
// สร้าง thumbnails
if (isset($config['thumbnails'])) {
foreach ($config['thumbnails'] as $size) {
$thumbName = $baseName . '_thumb_' . $size . '.' . $extension;
$thumbPath = $baseDir . 'thumbnails/' . $thumbName;
File::makeDirectory(dirname($thumbPath) . '/', 0755);
$watermark = $config['watermark'] ? '© My Website' : '';
if (Image::resize($imagePath, dirname($thumbPath) . '/', $thumbName, $size, $watermark)) {
$result['thumbnails'][$size] = $thumbPath;
}
}
}
return $result;
}
private function saveFileRecord($fileData, $category, $userId)
{
$record = [
'user_id' => $userId,
'category' => $category,
'original_path' => $fileData['original_path'],
'file_size' => $fileData['file_size'],
'thumbnails' => isset($fileData['thumbnails']) ? json_encode($fileData['thumbnails']) : null,
'uploaded_at' => date('Y-m-d H:i:s')
];
$fileId = Kotchasan\Database::create()
->insert('uploaded_files')
->values($record)
->execute();
return array_merge($record, ['id' => $fileId]);
}
}ระบบจัดการรูปภาพ Gallery
class GalleryManager
{
public function createGallery($images, $albumId)
{
$galleryPath = '/var/www/uploads/gallery/' . $albumId . '/';
File::makeDirectory($galleryPath, 0755);
$processedImages = [];
foreach ($images as $uploadedImage) {
try {
$result = $this->processGalleryImage($uploadedImage, $galleryPath);
$processedImages[] = $result;
} catch (Exception $e) {
// Log error และข้ามรูปที่มีปัญหา
error_log("Gallery processing error: " . $e->getMessage());
}
}
return $processedImages;
}
private function processGalleryImage($uploadedImage, $galleryPath)
{
// สร้างชื่อไฟล์
$fileName = uniqid() . '.jpg';
$originalPath = $galleryPath . 'originals/' . $fileName;
// สร้างไดเรกทอรีย่อย
File::makeDirectory(dirname($originalPath) . '/', 0755);
File::makeDirectory($galleryPath . 'thumbnails/', 0755);
File::makeDirectory($galleryPath . 'display/', 0755);
// บันทึกไฟล์ต้นฉบับ
$uploadedImage->moveTo($originalPath);
// สร้างรูปสำหรับแสดงผล (1200px max)
$displayPath = $galleryPath . 'display/' . $fileName;
Image::resize($originalPath, dirname($displayPath) . '/', basename($displayPath), 1200, '© Gallery 2024');
// สร้าง thumbnail (300px)
$thumbnailPath = $galleryPath . 'thumbnails/' . $fileName;
Image::crop($originalPath, $thumbnailPath, 300, 300, '', false);
return [
'filename' => $fileName,
'original_path' => $originalPath,
'display_path' => $displayPath,
'thumbnail_path' => $thumbnailPath,
'file_size' => filesize($originalPath)
];
}
$outputSize = 120; // 0)
{
$galleryPath = '/var/www/uploads/gallery/' . $albumId . '/';
$thumbnailDir = $galleryPath . 'thumbnails/';
$thumbnails = [];
File::listFiles($thumbnailDir, $thumbnails, ['jpg', 'jpeg', 'png']);
if (count($thumbnails) < 4) {
throw new Exception("ต้องมีรูปภาพอย่างน้อย 4 รูป");
}
// สร้าง mosaic 2x2
$tileSize = $outputSize / 2;
$mosaic = imagecreatetruecolor($outputSize, $outputSize);
$positions = [
[0, 0], [$tileSize, 0],
[0, $tileSize], [$tileSize, $tileSize]
];
for ($i = 0; $i < 4 && $i < count($thumbnails); $i++) {
$thumbnail = Image::loadImageResource($thumbnails[$i]);
$resized = Image::processImageResource($thumbnail, $tileSize, $tileSize, '', false);
imagecopy($mosaic, $resized, $positions[$i][0], $positions[$i][1], 0, 0, $tileSize, $tileSize);
imagedestroy($resized);
imagedestroy($thumbnail);
}
$mosaicPath = $galleryPath . 'mosaic.jpg';
Image::saveImageResource($mosaic, $mosaicPath);
imagedestroy($mosaic);
return $mosaicPath;
}
}Best Practices
1. ความปลอดภัยของไฟล์
// ✅ ดี - ตรวจสอบประเภทไฟล์อย่างเข้มงวด
function validateFileSecurely($uploadedFile) {
// ตรวจสอบ extension
$allowedExts = ['jpg', 'jpeg', 'png', 'pdf'];
if (!$uploadedFile->validFileExt($allowedExts)) {
throw new Exception("ประเภทไฟล์ไม่ได้รับอนุญาต");
}
// ตรวจสอบ MIME type
$allowedMimes = ['image/jpeg', 'image/png', 'application/pdf'];
if (!in_array($uploadedFile->getClientMediaType(), $allowedMimes)) {
throw new Exception("MIME type ไม่ได้รับอนุญาต");
}
// ตรวจสอบเนื้อหาไฟล์จริง
$finfo = new finfo(FILEINFO_MIME_TYPE);
$realMime = $finfo->file($uploadedFile->getTempFileName());
if (!in_array($realMime, $allowedMimes)) {
throw new Exception("เนื้อหาไฟล์ไม่ตรงกับประเภทที่ประกาศ");
}
}
// ✅ ดี - สร้างชื่อไฟล์ที่ปลอดภัย
function generateSecureFileName($uploadedFile) {
$extension = strtolower(pathinfo($uploadedFile->getClientFilename(), PATHINFO_EXTENSION));
return hash('sha256', uniqid() . time() . $uploadedFile->getClientFilename()) . '.' . $extension;
}2. การจัดการข้อผิดพลาด
// ✅ ดี - จัดการ exception อย่างเหมาะสม
class FileHandler
{
public function handleUpload($uploadedFile)
{
try {
$this->validateFile($uploadedFile);
$path = $this->saveFile($uploadedFile);
$this->logSuccess($path);
return $path;
} catch (InvalidArgumentException $e) {
$this->logError("Validation error", $e);
throw new Exception("ไฟล์ไม่ถูกต้อง: " . $e->getMessage());
} catch (RuntimeException $e) {
$this->logError("Runtime error", $e);
throw new Exception("ไม่สามารถจัดเก็บไฟล์ได้");
} catch (Exception $e) {
$this->logError("Unexpected error", $e);
throw new Exception("เกิดข้อผิดพลาดไม่คาดคิด");
}
}
private function logError($type, $exception)
{
error_log("File upload {$type}: " . $exception->getMessage());
}
private function logSuccess($path)
{
error_log("File uploaded successfully: " . $path);
}
}3. การเพิ่มประสิทธิภาพ
// ✅ ดี - ใช้ memory อย่างมีประสิทธิภาพ
class OptimizedImageProcessor
{
public function processBatchImages($imagePaths, $outputDir)
{
foreach ($imagePaths as $imagePath) {
$this->processImageMemoryEfficient($imagePath, $outputDir);
}
}
private function processImageMemoryEfficient($imagePath, $outputDir)
{
try {
// โหลดรูปภาพ
$imageResource = Image::loadImageResource($imagePath);
// ประมวลผล
$processed = Image::processImageResource($imageResource, 800, 0, '', false);
// บันทึก
$outputPath = $outputDir . basename($imagePath);
Image::saveImageResource($processed, $outputPath);
} finally {
// ทำลาย resource เสมอ
if (isset($processed) && is_resource($processed)) {
imagedestroy($processed);
}
if (isset($imageResource) && is_resource($imageResource)) {
imagedestroy($imageResource);
}
}
}
}
// ✅ ดี - Lazy loading สำหรับรายการไฟล์ขนาดใหญ่
class FileListManager
{
$limit = 5; // 0)
{
$allFiles = [];
File::listFiles($directory, $allFiles);
$totalFiles = count($allFiles);
$offset = ($page - 1) * $limit;
$pagedFiles = array_slice($allFiles, $offset, $limit);
return [
'files' => $pagedFiles,
'pagination' => [
'current_page' => $page,
'total_pages' => ceil($totalFiles / $limit),
'total_files' => $totalFiles
]
];
}
}4. การทำความสะอาดและบำรุงรักษา
// ✅ ดี - ระบบทำความสะอาดอัตโนมัติ
class FileMaintenance
{
public function cleanupExpiredFiles()
{
$tempDir = '/var/www/uploads/temp/';
$expiredTime = time() - (24 60 60); // 24 ชั่วโมง
$tempFiles = [];
File::listFiles($tempDir, $tempFiles);
$deletedCount = 0;
foreach ($tempFiles as $file) {
if (filemtime($file) < $expiredTime) {
if (unlink($file)) {
$deletedCount++;
}
}
}
return $deletedCount;
}
public function optimizeImageDirectory($directory)
{
$imageFiles = [];
File::listFiles($directory, $imageFiles, ['jpg', 'jpeg', 'png']);
$optimizedCount = 0;
foreach ($imageFiles as $imagePath) {
$originalSize = filesize($imagePath);
// ลด quality ถ้าไฟล์ใหญ่เกินไป
if ($originalSize > 1024 * 1024) { // > 1MB
$quality = 7; // 0;
$backupPath = $imagePath . '.backup';
rename($imagePath, $backupPath);
if (Image::resize($backupPath, dirname($imagePath) . '/', basename($imagePath), 0, '')) {
$newSize = filesize($imagePath);
if ($newSize < $originalSize) {
unlink($backupPath);
$optimizedCount++;
} else {
rename($backupPath, $imagePath);
}
}
}
}
return $optimizedCount;
}
}การจัดการไฟล์และรูปภาพใน Kotchasan Framework ให้ความยืดหยุ่นและความปลอดภัยสูง ควรใช้งานอย่างระมัดระวังและติดตาม best practices เพื่อประสิทธิภาพและความปลอดภัยสูงสุด