file_path = $file_array['tmp_name'];
$this->file_size = $file_array['size'];
$this->file_type = $file_array['type'];
$this->save_path = $save_path;
}
public function set_allow_type($allow_type) { $this->allow_type = $allow_type; }
public function set_allow_size($allow_size) { $this->allow_size = $allow_size; }
// 主入口
public function uploadfile()
{
if (!$this->allow_file_type()) {
$this->file_name(); // 仍生成文件名供錯誤時參考
}
if (move_uploaded_file($this->file_path, $this->save_path . $this->file_name)) {
return true;
} else {
$this->error = "文件上傳失敗";
return false;
}
}
private function allow_file_type()
{
$this->file_name();
if (in_array($this->mime_type, $this->allow_type)) return true;
$this->error = "不允許上傳的類型";
return false;
}
public function allow_file_size($size = 100) // 單位 KB?
{
if ($this->is_limit_size) {
$this->set_allow_size($size * 1024); // 轉字節
if ($this->allow_size >= $this->file_size) return true;
$this->error = "超過文件上傳大小限制";
}
return false;
}
public function is_limit_size() { $this->is_limit_size = true; }
private function file_name()
{
$this->mime_type = substr($this->file_type, strpos($this->file_type, '/') + 1);
if ($this->mime_type == 'pjpeg') $this->mime_type = 'jpg';
if ($this->mime_type == 'x-ms-wma') $this->mime_type = 'wma';
if ($this->mime_type == 'x-ms-wmv') $this->mime_type = 'wmv';
$this->file_name = date("YmdHis") . ".$this->mime_type";
}
public function _get_file_name() { return $this->file_name; }
}
?>
set_allow_type(['jpg','jpeg','gif']);
$file->is_limit_size();
if (!$file->allow_file_size(500)) { // 500KB
echo $file->error; exit;
}
if (!$file->allow_file_type()) {
echo $file->error; exit;
}
if (!$file->uploadfile()) {
echo $file->error; exit;
}
echo "上傳成功,文件名: " . $file->_get_file_name();
?>
| 問題 | 現狀 | 建議 |
|---|---|---|
| 構造函數名 | class_file() (PHP4 風格) | 改為 __construct() |
| 類型驗證依賴 MIME | $_FILES['type'] 可偽造 | 上傳後用 finfo_file() 二次驗證 |
| 大小單位混淆 | allow_file_size(500) 內部乘 1024 | 統一用字節,文檔標註單位 |
| 錯誤處理 | 公共 $error 字符串 | 拋出異常或返回 Result 對象 |
| 文件名衝突 | 時間戳秒級 | 增加 microtime(true) 或隨機串 |
| 目錄不存在 | 無自動創建 | mkdir($save_path, 0755, true) |
class FileUploader
{
private $config;
public function __construct(array $config) { $this->config = $config + ['maxSize'=>2*1024*1024, 'allowTypes'=>[]]; }
public function upload(array $file): array
{
$this->validate($file);
$ext = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
$name = bin2hex(random_bytes(8)) . ".$ext";
$dest = rtrim($this->config['savePath'], '/') . "/$name";
if (!move_uploaded_file($file['tmp_name'], $dest)) {
throw new RuntimeException('Move failed');
}
return ['path'=>$dest, 'name'=>$name, 'size'=>$file['size']];
}
private function validate(array $file) { /* MIME、大小、錯誤碼 */ }
}
本類展示了 PHP 早期面向過程封裝的典型結構:屬性保狀態、Setter 配置、驗證鏈、執行入口。理解其邏輯有助於閱讀老項目代碼;新項目請採用異常驅動、依賴注入、存儲抽象的現代設計。