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

PHP 多圖片上傳類別完整實作 (類型驗證、大小限制、隨機命名)

     編輯:PHP 綜合知識

類別功能特色

  • 支援 GIF/JPG/PNG 等圖片格式
  • MIME 型別 + 檔頭魔術位元組雙重驗證 (防偽裝上傳)
  • 單檔/總大小限制
  • 隨機 MD5 檔名避免衝突
  • 上傳目錄可配置
  • 詳細錯誤碼與訊息回報

完整類別程式碼

 '474946',      // GIF87a/89a
        'jpg'  => 'FFD8FF',      // JPEG
        'png'  => '89504E47',    // PNG
    ];

    private $files = [];
    private $totalSize = 0;
    private $errors = [];

    public function __construct(array $files = [])
    {
        $this->files = $files ?: $_FILES;
    }

    public function upload(): array
    {
        $results = [];
        foreach ($this->files['name'] as $idx => $name) {
            $error = $this->files['error'][$idx];
            $tmp   = $this->files['tmp_name'][$idx];
            $size  = $this->files['size'][$idx];
            $mime  = $this->files['type'][$idx];

            if ($error !== UPLOAD_ERR_OK) {
                $results[] = $this->result($name, $mime, $size, $this->errorMsg($error), false);
                continue;
            }

            if ($size > self::MAX_FILE_SIZE) {
                $results[] = $this->result($name, $mime, $size, '單檔超過大小限制', false);
                continue;
            }

            if ($this->totalSize + $size > self::MAX_TOTAL_SIZE) {
                $results[] = $this->result($name, $mime, $size, '總大小超過限制', false);
                continue;
            }

            if (!$this->validateType($tmp, $mime)) {
                $results[] = $this->result($name, $mime, $size, '檔案類型不符', false);
                continue;
            }

            $destName = $this->randomName(pathinfo($name, PATHINFO_EXTENSION));
            $destPath = $_SERVER['DOCUMENT_ROOT'] . self::UPLOAD_DIR . $destName;

            if (!is_dir(dirname($destPath))) mkdir(dirname($destPath), 0755, true);
            if (move_uploaded_file($tmp, $destPath)) {
                $this->totalSize += $size;
                $results[] = $this->result($name, $mime, $size, '上傳成功', true, $destName);
            } else {
                $results[] = $this->result($name, $mime, $size, '移動檔案失敗', false);
            }
        }
        return $results;
    }

    private function validateType(string $tmp, string $mime): bool
    {
        if (!in_array($mime, $this->allowedMimes, true)) return false;
        $bytes = bin2hex(file_get_contents($tmp, false, null, 0, 8));
        foreach ($this->magicBytes as $ext => $magic) {
            if (stripos($bytes, $magic) === 0) return true;
        }
        return false;
    }

    private function randomName(string $ext): string
    {
        return md5(uniqid(microtime(true), true)) . '.' . strtolower($ext);
    }

    private function errorMsg(int $code): string
    {
        return match ($code) {
            UPLOAD_ERR_INI_SIZE, UPLOAD_ERR_FORM_SIZE => '檔案超過大小限制',
            UPLOAD_ERR_PARTIAL => '檔案上傳不完整',
            UPLOAD_ERR_NO_FILE => '未選擇檔案',
            UPLOAD_ERR_NO_TMP_DIR => '缺少暫存目錄',
            UPLOAD_ERR_CANT_WRITE => '寫入失敗',
            UPLOAD_ERR_EXTENSION => '擴展阻止上傳',
            default => '未知錯誤',
        };
    }

    private function result(string $orig, string $mime, int $size, string $msg, bool $ok, string $saved = ''): array
    {
        return [
            'original_name' => $orig,
            'mime' => $mime,
            'size' => $this->formatSize($size),
            'message' => $msg,
            'success' => $ok,
            'saved_name' => $saved,
        ];
    }

    private function formatSize(int $bytes): string
    {
        if ($bytes < 1024) return $bytes . ' B';
        if ($bytes < 1024 * 1024) return round($bytes / 1024, 1) . ' KB';
        return round($bytes / (1024 * 1024), 1) . ' MB';
    }
}

使用範例



require 'MultiFileUpload.php';
$uploader = new MultiFileUpload();
$results = $uploader->upload();

foreach ($results as $r) {
    echo "{$r['original_name']} | {$r['size']} | {$r['message']}";
    if ($r['success']) echo " → saved as {$r['saved_name']}";
    echo "
\n"; }

安全性補充

  • 上傳目錄**禁止執行腳本** (Nginx: location /uploadfile { php_flag engine off; })
  • 檔案副檔名**白名單驗證**,不要信任用戶提供的副檔名
  • 資料庫儲存路徑使用**隨機名稱**,原始檔名另存欄位
  • 考慮整合病毒掃描 (ClamAV) 或圖片重繪 (imagecreatefromstring → imagejpeg) 清除潛在惡意代碼
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved