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

PHP 圖片上傳類完整實現(含預覽、類型驗證、錯誤處理)

     編輯:PHP 綜合知識

類設計目標

  • 支持多種圖片格式(JPG、PNG、GIF、BMP 等)
  • 文件大小限制、MIME 類型雙重驗證
  • 自動創建存儲目錄、生成唯一文件名
  • 可選生成縮略圖預覽
  • 統一異常處理與友好提示

核心類代碼

<?php
class ImageUploader {
    // 配置屬性
    private $uploadDir = './uploads/';
    private $allowedTypes = ['image/jpeg', 'image/png', 'image/gif', 'image/bmp', 'image/webp'];
    private $maxSize = 2 * 1024 * 1024; // 2MB
    private $thumbRatio = 0.2;          // 縮略圖比例
    private $createThumb = true;

    // 運行時屬性
    private $fileName;
    private $tmpName;
    private $fileSize;
    private $fileType;
    private $imageInfo;

    public function __construct(array $config = []) {
        foreach ($config as $key => $val) {
            if (property_exists($this, $key)) $this->$key = $val;
        }
    }

    public function upload(array $file): array {
        $this->init($file);
        $this->validate();
        $this->save();
        return $this->getResult();
    }

    private function init(array $file) {
        $this->tmpName = $file['tmp_name'];
        $this->fileName = $file['name'];
        $this->fileSize = $file['size'];
        $this->fileType = $file['type'];
        $this->imageInfo = getimagesize($this->tmpName);
        if (!$this->imageInfo) throw new Exception('非法圖片文件');
    }

    private function validate() {
        if (!is_dir($this->uploadDir)) mkdir($this->uploadDir, 0755, true);
        
        if ($this->fileSize > $this->maxSize) 
            throw new Exception('文件大小超過限制 (' . ($this->maxSize/1024/1024) . 'MB)');
        
        if (!in_array($this->fileType, $this->allowedTypes))
            throw new Exception('不支持的文件類型:' . $this->fileType);
    }

    private function save() {
        $ext = strtolower(pathinfo($this->fileName, PATHINFO_EXTENSION));
        $newName = date('YmdHis') . '_' . uniqid() . '.' . $ext;
        $destPath = $this->uploadDir . $newName;
        
        if (!move_uploaded_file($this->tmpName, $destPath))
            throw new Exception('文件移動失敗,請檢查目錄權限');
        
        $this->fileName = $newName;
        $this->destPath = $destPath;
    }

    private function getResult(): array {
        $result = [
            'success' => true,
            'filename' => $this->fileName,
            'path' => $this->destPath,
            'url' => $this->destPath, // 相對 Web 根目錄的 URL
            'size' => $this->fileSize,
            'width' => $this->imageInfo[0],
            'height' => $this->imageInfo[1],
        ];
        
        if ($this->createThumb) {
            $result['thumb'] = $this->createThumbnail();
        }
        return $result;
    }

    private function createThumbnail(): string {
        // 簡易縮略:直接縮放尺寸屬性,實際項目建議用 GD/Imagick 生成物理縮略圖
        $w = $this->imageInfo[0] * $this->thumbRatio;
        $h = $this->imageInfo[1] * $this->thumbRatio;
        return '<img src="' . $this->destPath . '" width="' . $w . '" height="' . $h . '">';
    }
}

前端表單

<form action="upload.php" method="post" enctype="multipart/form-data">
    <input type="file" name="photo" accept="image/*" required>
    <button type="submit">上傳圖片</button>
</form>

處理頁面

<?php
require 'ImageUploader.php';
header('Content-Type: application/json; charset=utf-8');

if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    exit(json_encode(['success' => false, 'msg' => '請求方式錯誤']));
}

try {
    $uploader = new ImageUploader([
        'uploadDir' => __DIR__ . '/public/uploads/',
        'maxSize' => 5 * 1024 * 1024,
    ]);
    $result = $uploader->upload($_FILES['photo']);
    echo json_encode($result);
} catch (Exception $e) {
    http_response_code(400);
    echo json_encode(['success' => false, 'msg' => $e->getMessage()]);
}

安全加固清單

  1. 禁用腳本執行權限: 上傳目錄配置 Nginx/Apache 禁止 PHP 執行。
  2. 二次驗證文件內容: 使用 finfo_file() 檢測真實 MIME,防止偽造 Content-Type。
  3. 文件名去敏: 不保留用戶原始文件名,防止路徑遍歷攻擊。
  4. 病毒掃描: 生產環境接入 ClamAV 等掃描引擎。
  5. 限制並發與總量: 防止磁盤被寫滿。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved