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

五分鐘打造通用 PHP 上傳類:類型檢查、大小限制、自動分目錄、刪除管理

     編輯:PHP 相關知識

類別設計目標

  • 單一職責:封裝上傳、驗證、儲存、刪除全流程。
  • 配置化:副檔名白名單、大小限制、儲存根目錄可外部注入。
  • 安全第一:路徑遍歷防護、MIME 驗證、隨機檔名、權限控制。
  • 易擴展:支援多儲存驅動(本地、S3、FTP)預留介面。

核心代碼 (upLoad.class.php)

<?php
class upLoad {
    private $root = '/var/www/uploads';   // 儲存根目錄
    private $typeWhitelist = ['jpg','jpeg','png','gif','pdf','zip'];
    private $maxSize = 5 * 1024 * 1024;   // 5MB

    // ---------- 公開介面 ----------
    public function init($fieldName, $maxSize = null) {
        if (!isset($_FILES[$fieldName]) || $_FILES[$fieldName]['error'] !== UPLOAD_ERR_OK) {
            return false;
        }
        $this->maxSize = $maxSize ?? $this->maxSize;
        $file = $_FILES[$fieldName];

        if (!$this->_checkType($file['name']) || !$this->_checkSize($file['size']) || $file['error'] !== 0) {
            return false;
        }

        $destDir = $this->_createUserDir('user_' . session_id()); // 實際專案用 user_id
        $newName = $this->_genRandomName($file['name']);
        $destPath = $destDir . $newName;

        return @move_uploaded_file($file['tmp_name'], $destPath) ? $newName : false;
    }

    public function deleteFile($relativePath) {
        $full = $this->root . '/' . ltrim($relativePath, '/');
        if ($this->_isInsideRoot($full) && is_file($full)) {
            return @unlink($full);
        }
        return false;
    }

    public function deleteDir($relativePath) {
        $full = $this->root . '/' . ltrim($relativePath, '/');
        if ($this->_isInsideRoot($full) && is_dir($full)) {
            return @rmdir($full); // 僅刪除空目錄,遞歸刪除需自行實現
        }
        return false;
    }

    // ---------- 內部邏輯 ----------
    private function _checkType($fileName) {
        $ext = strtolower(pathinfo($fileName, PATHINFO_EXTENSION));
        // 可選:檢查多重副檔名 (evil.php.jpg)
        if (substr_count($fileName, '.') > 1) return false;
        return in_array($ext, $this->typeWhitelist);
    }

    private function _checkSize($size) {
        return $size <= $this->maxSize;
    }

    private function _genRandomName($origName) {
        $ext = strtolower(pathinfo($origName, PATHINFO_EXTENSION));
        return bin2hex(random_bytes(16)) . '.' . $ext;
    }

    private function _createUserDir($userId) {
        $datePath = date('Y/m/d/');
        $path = $this->root . '/' . $datePath . $userId . '/';
        if (!is_dir($path)) {
            mkdir($path, 0755, true); // 遞歸建立
        }
        return $path;
    }

    private function _isInsideRoot($path) {
        $realRoot = realpath($this->root);
        $realPath = realpath($path);
        return $realPath && strpos($realPath, $realRoot) === 0;
    }
}
?>

使用範例

<?php
require_once 'upLoad.class.php';
$uploader = new upLoad();

if ($savedName = $uploader->init('fileField')) {
    echo "上傳成功,儲存為:$savedName";
} else {
    echo "上傳失敗:" . $_FILES['fileField']['error'];
}

// 刪除範例
// $uploader->deleteFile('2024/05/20/user_abc123/a1b2c3d4.jpg');
?>

擴展建議

  1. 實作 StorageInterface,支援 AWS S3、阿里云 OSS、FTP 等雲端儲存。
  2. 加入圖片自動壓縮(Intervention/Image)、病毒掃描回調。
  3. 上傳日誌寫入資料庫:用戶、原始檔名、儲存路徑、大小、MIME、IP、時間。
  4. 大檔分片上傳:前端 Plupload/Uppy + 後端合併臨時分片。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved