upload 類別封裝完整上傳流程:檔案類型/大小驗證、日期分層目錄自動建立、多檔上傳、等比縮圖、圖片浮水印(支援透明度/位置)、回傳結構化結果。採用屬性設定模式,靈活組合功能。
class upload {
var $dir, $time, $allow_types, $field, $maxsize;
var $thumb_width, $thumb_height;
var $watermark_file, $watermark_pos, $watermark_trans;
function __construct($types = 'jpg|png', $maxsize = 1024, $field = 'attach', $time = '') {
$this->allow_types = explode('|', $types);
$this->maxsize = $maxsize * 1024; // KB → Bytes
$this->field = $field;
$this->time = $time ? $time : time();
}
// 設定儲存目錄:支援 {y}{m}{d} 日期佔位符
function set_dir($basedir, $filedir = '') {
$dir = $basedir;
!is_dir($dir) && @mkdir($dir, 0777);
if (!empty($filedir)) {
$filedir = str_replace(array('{y}','{m}','{d}'), array(date('Y',$this->time), date('m',$this->time), date('d',$this->time)), strtolower($filedir));
foreach (explode('/',$filedir) as $d) {
!empty($d) && $dir .= $d.'/';
!is_dir($dir) && @mkdir($dir, 0777);
}
}
$this->dir = $dir;
}
// 執行上傳主流程
function execute() {
$files = array();
$keys = array_keys($_FILES[$this->field]['name']);
foreach ($keys as $key) {
if (!$_FILES[$this->field]['name'][$key]) continue;
$fileext = $this->fileext($_FILES[$this->field]['name'][$key]);
$filename = date('Ymdhis', $this->time) . mt_rand(10,99) . '.' . $fileext;
$filedir = $this->dir;
$filesize = $_FILES[$this->field]['size'][$key];
// 驗證類型與大小
if (!in_array($fileext, $this->allow_types)) { $files[$key] = array('name'=>$_FILES[$this->field]['name'][$key], 'flag'=>-1); continue; }
if ($filesize > $this->maxsize) { $files[$key] = array('name'=>$_FILES[$this->field]['name'][$key], 'size'=>$filesize, 'flag'=>-2); continue; }
$files[$key] = array('name'=>$filename, 'dir'=>$filedir, 'size'=>$filesize);
// 移動檔案
if (is_uploaded_file($_FILES[$this->field]['tmp_name'][$key])) {
move_uploaded_file($_FILES[$this->field]['tmp_name'][$key], $filedir.$filename);
@unlink($_FILES[$this->field]['tmp_name'][$key]);
$files[$key]['flag'] = 1;
// 圖片後處理
if (in_array($fileext, array('jpg','png'))) {
if ($this->thumb_width) {
if ($this->create_thumb($filedir.$filename, $filedir.'thumb_'.$filename)) {
$files[$key]['thumb'] = 'thumb_'.$filename;
}
}
$this->create_watermark($filedir.$filename);
}
}
}
return $files;
}
// 等比縮圖(支援 jpg/png/gif)
function create_thumb($src_file, $thumb_file) {
// ... 完整程式碼見原文,關鍵點:
// 1. 來源圖小於目標尺寸直接複製
// 2. 依長邊比例計算縮放
// 3. 優先 imagecopyresampled,退而求其次 imagecopyresized
// 4. 依副檔名呼叫對應輸出函式
}
// 圖片浮水印(疊加 PNG/GIF/JPG 水印圖)
function create_watermark($file) {
// ... 完整程式碼見原文,關鍵點:
// 1. 檢查 GD 支援格式與檔案存在
// 2. 圖片尺寸檢查(背景需大於水印)
// 3. 9 種位置模式(四角、四邊中、置中、隨機)
// 4. imageCopyMerge 支援透明度合成
// 5. 覆蓋原檔輸出
}
function fileext($filename) {
return strtolower(substr(strrchr($filename,'.'), 1, 10));
}
}
set_dir(dirname(__FILE__).'/upload/', '{y}/{m}'); // 基礎目錄 + 年/月子目錄
$up->set_thumb(100, 80); // 縮圖最大 100x80
$up->set_watermark(dirname(__FILE__).'/watermark.png', 6, 90); // 水印檔、右下角、90% 不透明
$fs = $up->execute();
var_dump($fs);
}
?>
Array
(
[0] => Array
(
[name] => 20240115143025_45.jpg // 伺服器檔名
[dir] => /var/www/upload/2024/01/ // 實體路徑
[size] => 102456 // 位元組
[flag] => 1 // 1=成功, -1=類型錯誤, -2=超過大小
[thumb] => thumb_20240115143025_45.jpg // 縮圖檔名(若啟用)
)
// ... 多檔案依序
)
finfo_file() 驗證真實類型,防副檔名偽裝日期+隨機數 可改用 uniqid('', true) 或 hash('sha256', ...)imagecreatefromstring() 重讀並儲存,清除潛在惡意代碼