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

PHP 檔案上傳常見問題總整理:驗證、重命名、分目錄、多檔、大檔案完整指南

     編輯:PHP 綜合知識

檔案上傳是 Web 開發核心功能,但細節陷阱眾多。本文系統整理 7 大常見場景:基礎上傳、$_FILES 結構、MIME 驗證、重名處理、日期分目錄、多檔上傳、大檔案配置,提供生產級程式碼與最佳實踐。

1. 基礎上傳表單與處理

<form action="upload.php" method="post" enctype="multipart/form-data">
    <input type="file" name="file" id="file" required>
    <input type="hidden" name="MAX_FILE_SIZE" value="2000000"> <!-- 2MB 客戶端提示 -->
    <button type="submit">上傳</button>
</form>
<?php
// 基礎驗證
if ($_FILES['file']['error'] !== UPLOAD_ERR_OK) {
    die('上傳錯誤: ' . $_FILES['file']['error']);
}

if ($_FILES['file']['size'] > 2_000_000) {
    die('檔案過大');
}

$dest = 'uploads/' . basename($_FILES['file']['name']);
if (move_uploaded_file($_FILES['file']['tmp_name'], $dest)) {
    echo "上傳成功: $dest";
}
?>

2. $_FILES 結構與錯誤碼對照

鍵名說明
name用戶端原始檔名
type瀏覽器報告 MIME (不可信)
size檔案大小 (位元組)
tmp_name伺服器暫存路徑
error錯誤碼 (見下表)
常數值說明
UPLOAD_ERR_OK0成功
UPLOAD_ERR_INI_SIZE1超過 php.ini upload_max_filesize
UPLOAD_ERR_FORM_SIZE2超過表單 MAX_FILE_SIZE
UPLOAD_ERR_PARTIAL3部分上傳 (網路中斷)
UPLOAD_ERR_NO_FILE4未選擇檔案
UPLOAD_ERR_NO_TMP_DIR6缺少暫存目錄
UPLOAD_ERR_CANT_WRITE7寫入失敗 (權限/磁碟滿)

3. MIME 類型驗證 (核心安全)

<?php
// ❌ 錯誤:信任 $_FILES['file']['type']
// ✅ 正確:使用 Fileinfo 擴展檢測實際內容
$finfo = new finfo(FILEINFO_MIME_TYPE);
$mime = $finfo->file($_FILES['file']['tmp_name']);

$allowed = ['image/jpeg', 'image/png', 'image/gif', 'image/webp', 'application/pdf'];
if (!in_array($mime, $allowed, true)) {
    die('檔案類型不允許: ' . $mime);
}
?>

4. 重名檔案自動重命名

<?php
function getUniqueFilename($dir, $filename) {
    $ext = pathinfo($filename, PATHINFO_EXTENSION);
    $base = basename($filename, '.' . $ext);
    $counter = 1;
    $newName = $filename;
    
    while (file_exists($dir . $newName)) {
        $newName = $base . '_' . $counter++ . ($ext ? '.' . $ext : '');
    }
    return $newName;
}

// 使用
$safeName = getUniqueFilename('uploads/', $_FILES['file']['name']);
move_uploaded_file($_FILES['file']['tmp_name'], 'uploads/' . $safeName);
?>

5. 依日期自動分目錄儲存

<?php
$dateDir = date('Y/m/d/'); // 2024/01/15/
$fullDir = 'uploads/' . $dateDir;

if (!is_dir($fullDir)) {
    mkdir($fullDir, 0755, true); // 遞迴建立
}

$dest = $fullDir . basename($_FILES['file']['name']);
move_uploaded_file($_FILES['file']['tmp_name'], $dest);
?>

6. 多檔案上傳處理

<form method="post" enctype="multipart/form-data">
    <input type="file" name="files[]" multiple>
    <button type="submit">上傳多檔</button>
</form>
<?php
// $_FILES 結構轉換:從「欄位優先」轉為「檔案優先」
function normalizeFilesArray($files) {
    $normalized = [];
    foreach ($files['name'] as $index => $name) {
        if ($files['error'][$index] === UPLOAD_ERR_OK) {
            $normalized[] = [
                'name' => $name,
                'type' => $files['type'][$index],
                'tmp_name' => $files['tmp_name'][$index],
                'size' => $files['size'][$index],
                'error' => $files['error'][$index],
            ];
        }
    }
    return $normalized;
}

$files = normalizeFilesArray($_FILES['files']);
foreach ($files as $file) {
    // 單檔處理邏輯...
}
?>

7. 大檔案上傳伺服器配置

配置項建議值說明
php.ini: upload_max_filesize100M單檔最大值
php.ini: post_max_size120MPOST 總大小 > upload_max_filesize
php.ini: max_execution_time300上傳處理最長秒數
php.ini: max_input_time300接收資料最長秒數
php.ini: memory_limit256M腳本記憶體上限
Nginx: client_max_body_size100MNginx 層面限制
Apache: LimitRequestBody104857600Apache 層面限制 (位元組)

分塊上傳 (超大檔案 > 100MB)

<?php
// 前端:將檔案切片 (如 5MB/片),並發上傳
// 後端:合併切片
function mergeChunks($chunkDir, $finalPath, $totalChunks) {
    $out = fopen($finalPath, 'wb');
    for ($i = 0; $i < $totalChunks; $i++) {
        $chunkFile = $chunkDir . "/part_$i";
        if (!file_exists($chunkFile)) {
            fclose($out);
            return false; // 缺片
        }
        $in = fopen($chunkFile, 'rb');
        stream_copy_to_stream($in, $out);
        fclose($in);
        unlink($chunkFile); // 清理切片
    }
    fclose($out);
    return true;
}
?>

安全檢查清單

  • ✅ MIME 類型白名單驗證 (Fileinfo)
  • ✅ 檔案大小限制 (雙重:客戶端 + 伺服端)
  • ✅ 檔名安全化 (移除路徑、特殊字元、生成唯一名)
  • ✅ 儲存目錄非 Web 可執行 (或設定 Nginx/Apache 禁用腳本執行)
  • ✅ 病毒掃描 (整合 ClamAV `clamscan`)
  • ✅ 速率限制 (防止濫用)
  • ✅ CSRF Token 保護表單
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved