首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 檔案上傳類別:支援單檔/多檔、類型大小限制、自動重命名 (1/2)

     編輯:PHP 相關知識

類別設計目標

  • 封裝上傳邏輯,對外提供簡單的 upload() 方法。
  • 支援單檔($_FILES['file'])與多檔($_FILES['files'] 陣列)。
  • 可配置允許類型、最大尺寸、儲存目錄、自動建立目錄。
  • 回傳結構化資訊:原始檔名、儲存檔名、尺寸、類型、錯誤訊息。

完整類別程式碼 (UploadHandler.php)

<?php
class UploadHandler {
    public $allowed_types = ['jpg','jpeg','png','gif','pdf','zip'];
    public $max_size = 2 * 1024 * 1024; // 2MB
    public $save_dir = 'uploads/';
    public $overwrite = false;

    public function __construct($config = []) {
        foreach ($config as $k => $v) {
            if (property_exists($this, $k)) $this->$k = $v;
        }
        if (!is_dir($this->save_dir)) {
            mkdir($this->save_dir, 0755, true);
        }
    }

    // 統一入口:自動判斷單檔/多檔
    public function upload($field_name) {
        if (!isset($_FILES[$field_name])) {
            return ['error' => '未接收到上傳欄位'];
        }
        $file = $_FILES[$field_name];
        // 多檔判斷:name 為陣列
        if (is_array($file['name'])) {
            return $this->uploadMultiple($file);
        } else {
            return [$this->processSingle($file)];
        }
    }

    private function uploadMultiple($file) {
        $results = [];
        $count = count($file['name']);
        for ($i = 0; $i < $count; $i++) {
            if ($file['error'][$i] === UPLOAD_ERR_NO_FILE) continue;
            $single = [
                'name' => $file['name'][$i],
                'type' => $file['type'][$i],
                'tmp_name' => $file['tmp_name'][$i],
                'error' => $file['error'][$i],
                'size' => $file['size'][$i]
            ];
            $results[] = $this->processSingle($single);
        }
        return $results;
    }

    private function processSingle($file) {
        $info = ['original_name' => $file['name']];
        // 錯誤代碼檢查
        if ($file['error'] !== UPLOAD_ERR_OK) {
            $info['error'] = $this->errorMessage($file['error']);
            return $info;
        }
        // 類型檢查(副檔名)
        $ext = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
        if (!in_array($ext, $this->allowed_types)) {
            $info['error'] = '檔案類型不允許';
            return $info;
        }
        // 大小檢查
        if ($file['size'] > $this->max_size) {
            $info['error'] = '檔案超過最大限制';
            return $info;
        }
        // MIME 二次驗證(建議)
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $mime = finfo_file($finfo, $file['tmp_name']);
        finfo_close($finfo);
        $allowed_mimes = [
            'jpg'=>'image/jpeg','jpeg'=>'image/jpeg','png'=>'image/png',
            'gif'=>'image/gif','pdf'=>'application/pdf','zip'=>'application/zip'
        ];
        if (!isset($allowed_mimes[$ext]) || $allowed_mimes[$ext] !== $mime) {
            $info['error'] = '檔案內容類型不符';
            return $info;
        }
        // 產生唯一檔名
        $new_name = date('YmdHis') . '_' . bin2hex(random_bytes(8)) . '.' . $ext;
        $dest = $this->save_dir . $new_name;
        if (!$this->overwrite && file_exists($dest)) {
            $info['error'] = '檔案已存在';
            return $info;
        }
        if (!move_uploaded_file($file['tmp_name'], $dest)) {
            $info['error'] = '移動檔案失敗';
            return $info;
        }
        $info['saved_name'] = $new_name;
        $info['saved_path'] = $dest;
        $info['size'] = $file['size'];
        $info['mime'] = $mime;
        $info['error'] = '';
        return $info;
    }

    private function errorMessage($code) {
        static $msgs = [
            UPLOAD_ERR_INI_SIZE => '超過 php.ini upload_max_filesize',
            UPLOAD_ERR_FORM_SIZE => '超過表單 MAX_FILE_SIZE',
            UPLOAD_ERR_PARTIAL => '檔案上傳不完整',
            UPLOAD_ERR_NO_FILE => '未選擇檔案',
            UPLOAD_ERR_NO_TMP_DIR => '缺少暫存目錄',
            UPLOAD_ERR_CANT_WRITE => '寫入磁碟失敗',
            UPLOAD_ERR_EXTENSION => '被 PHP 擴充阻擋',
        ];
        return $msgs[$code] ?? '未知錯誤';
    }
}
?>

使用範例

<?php
require 'UploadHandler.php';

$uploader = new UploadHandler([
    'allowed_types' => ['jpg','png','gif'],
    'max_size' => 5 * 1024 * 1024,
    'save_dir' => 'data/uploads/'
]);

// 前端 
$results = $uploader->upload('photos');
foreach ($results as $r) {
    if ($r['error']) {
        echo "失敗:{$r['original_name']} - {$r['error']}<br>";
    } else {
        echo "成功:{$r['original_name']} → {$r['saved_name']} ({$r['size']} bytes)<br>";
    }
}
?>

下一章預告

第 2 部分將介紹:圖片自動縮圖(GD/Imagick)、上傳進度條(Session upload progress)、雲端儲存對接(S3/OSS)、資料庫記錄與軟刪除機制。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved