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

PHP 多文件上傳類實現:支援驗證、重命名與錯誤處理

     編輯:PHP 相關知識

功能特性

  • 支援多文件同時上傳
  • 文件類型白名單驗證(圖片、文檔等)
  • 文件大小限制
  • 自動生成唯一文件名(隨機字符+時間戳)
  • 按年月自動建立上傳目錄
  • 詳細的上傳結果表格輸出

核心類代碼

<?php
class MultiFileUpload {
    const UPLOAD_PATH = '../filehandle/uploadfile/';
    const MAX_SIZE = 81200000; // 80MB

    private $allowedTypes = [
        'text/plain', 'image/gif', 'image/jpeg', 'image/png',
        'text/html', 'application/msword', 'application/pdf'
    ];
    private $uploadDir;
    private $totalSize = 0;
    private $results = [];

    public function __construct(array $files) {
        $this->uploadDir = $this->getUploadDir();
        $this->processFiles($files);
    }

    private function getUploadDir(): string {
        $base = rtrim(self::UPLOAD_PATH, '/');
        $dir = $base . '/' . date('Ym');
        if (!is_dir($dir)) {
            mkdir($dir, 0755, true);
        }
        return $dir . '/';
    }

    private function processFiles(array $files): void {
        foreach ($files as $file) {
            if ($file['error'] !== UPLOAD_ERR_OK) {
                $this->addResult($file['name'], $file['type'], $file['size'], $this->getErrorMessage($file['error']));
                continue;
            }

            if (!in_array($file['type'], $this->allowedTypes)) {
                $this->addResult($file['name'], $file['type'], $file['size'], '文件類型不允許上傳');
                continue;
            }

            if ($file['size'] > self::MAX_SIZE) {
                $this->addResult($file['name'], $file['type'], $file['size'], '文件超過大小限制');
                continue;
            }

            $newName = $this->generateFileName($file['name']);
            $dest = $this->uploadDir . $newName;

            if (move_uploaded_file($file['tmp_name'], $dest)) {
                $this->totalSize += $file['size'];
                $this->addResult($file['name'], $file['type'], $file['size'], '上傳成功', $newName);
            } else {
                $this->addResult($file['name'], $file['type'], $file['size'], '文件移動失敗');
            }
        }
    }

    private function generateFileName(string $originalName): string {
        $ext = strtolower(pathinfo($originalName, PATHINFO_EXTENSION));
        $rand = substr(str_shuffle('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'), 0, 10);
        return 'TTR_' . time() . $rand . '.' . $ext;
    }

    private function getErrorMessage(int $code): string {
        switch ($code) {
            case UPLOAD_ERR_INI_SIZE: return '文件超過 php.ini 限制';
            case UPLOAD_ERR_FORM_SIZE: return '文件超過表單 MAX_FILE_SIZE 限制';
            case UPLOAD_ERR_PARTIAL: return '文件僅部分上傳';
            case UPLOAD_ERR_NO_FILE: return '未選擇文件';
            default: return '未知錯誤';
        }
    }

    private function addResult(string $name, string $type, int $size, string $msg, string $savedName = ''): void {
        $this->results[] = [
            'original' => $name,
            'type' => $type,
            'size_kb' => round($size / 1024, 1),
            'message' => $msg,
            'saved_as' => $savedName
        ];
    }

    public function renderResults(): void {
        echo '<table border="1" cellpadding="5" cellspacing="0" width="90%" align="center">';
        echo '<tr><th>原文件名</th><th>類型</th><th>大小(KB)</th><th>結果</th><th>保存名稱</th></tr>';
        foreach ($this->results as $r) {
            echo '<tr>';
            echo '<td>' . htmlspecialchars($r['original']) . '</td>';
            echo '<td>' . htmlspecialchars($r['type']) . '</td>';
            echo '<td align="center">' . $r['size_kb'] . '</td>';
            echo '<td align="center">' . htmlspecialchars($r['message']) . '</td>';
            echo '<td align="center">' . htmlspecialchars($r['saved_as']) . '</td>';
            echo '</tr>';
        }
        echo '</table>';
        echo '<p>總計大小:' . round($this->totalSize / 1024 / 1024, 2) . ' MB</p>';
    }
}
?>

前端表單示例

<form action="upload.php" method="post" enctype="multipart/form-data">
    <input type="file" name="files[]" multiple><br>
    <input type="submit" value="上傳">
</form>

處理頁面 upload.php

<?php
require_once 'MultiFileUpload.php';

if ($_SERVER['REQUEST_METHOD'] === 'POST' && !empty($_FILES['files'])) {
    // 整理 $_FILES 結構以便遍歷
    $files = [];
    $count = count($_FILES['files']['name']);
    for ($i = 0; $i < $count; $i++) {
        $files[] = [
            'name' => $_FILES['files']['name'][$i],
            'type' => $_FILES['files']['type'][$i],
            'tmp_name' => $_FILES['files']['tmp_name'][$i],
            'error' => $_FILES['files']['error'][$i],
            'size' => $_FILES['files']['size'][$i]
        ];
    }

    $uploader = new MultiFileUpload($files);
    $uploader->renderResults();
}
?>

優化建議

  1. 生產環境請將允許類型、大小限制、上傳路徑提取到配置文件。
  2. 增加圖片二次驗證(如 getimagesize())防止偽裝文件。
  3. 上傳目錄應置於 Web 根目錄外,或通過 .htaccess 禁止腳本執行。
  4. 考慮使用 PDO 記錄上傳日誌到數據庫。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved