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

PHP 檔案上傳:類型限制、大小驗證與安全儲存完整實作

     編輯:PHP 相關知識

檔案上傳是 Web 應用高風險功能,必須嚴格驗證 MIME 類型、副檔名、檔案大小,並以隨機檔名儲存於非公開目錄,防止惡意腳本執行。

完整上傳處理流程

<?php
$allowedTypes = ['image/gif', 'image/jpeg', 'image/png', 'image/webp'];
$allowedExts  = ['gif', 'jpg', 'jpeg', 'png', 'webp'];
$maxSize = 2 * 1024 * 1024; // 2MB
$uploadDir = __DIR__ . '/uploads/';

if (!is_dir($uploadDir)) {
    mkdir($uploadDir, 0755, true);
}

if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['file'])) {
    $file = $_FILES['file'];

    // 1. 錯誤碼檢查
    if ($file['error'] !== UPLOAD_ERR_OK) {
        $errors = [
            UPLOAD_ERR_INI_SIZE => '超過 php.ini upload_max_filesize',
            UPLOAD_ERR_FORM_SIZE => '超過表單 MAX_FILE_SIZE',
            UPLOAD_ERR_PARTIAL => '上傳不完整',
            UPLOAD_ERR_NO_FILE => '未選擇檔案',
        ];
        die($errors[$file['error']] ?? '上傳錯誤');
    }

    // 2. 檔案大小
    if ($file['size'] > $maxSize) {
        die('檔案過大,限制 2MB');
    }

    // 3. MIME 類型(參考值,不可全信)
    $finfo = new finfo(FILEINFO_MIME_TYPE);
    $mime = $finfo->file($file['tmp_name']);
    if (!in_array($mime, $allowedTypes, true)) {
        die('不允許的檔案類型');
    }

    // 4. 副檔名驗證
    $ext = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
    if (!in_array($ext, $allowedExts, true)) {
        die('不允許的副檔名');
    }

    // 5. 進階:檢查圖片真實性(防偽裝)
    $imgInfo = getimagesize($file['tmp_name']);
    if ($imgInfo === false) {
        die('非有效圖片檔案');
    }
    // 可選:二次轉存確保無殘留腳本
    // $dst = imagecreatefromstring(file_get_contents($file['tmp_name']));
    // imagejpeg($dst, $newPath); imagedestroy($dst);

    // 6. 產生安全檔名
    $safeName = bin2hex(random_bytes(16)) . '.' . $ext;
    $destPath = $uploadDir . $safeName;

    // 7. 移動檔案
    if (!move_uploaded_file($file['tmp_name'], $destPath)) {
        die('檔案儲存失敗');
    }

    // 8. 設定檔案權限(不可執行)
    chmod($destPath, 0644);

    echo json_encode(['success' => true, 'path' => $safeName, 'url' => '/uploads/' . $safeName]);
}
?>

前端表單必要屬性

<form method="post" enctype="multipart/form-data">
  <input type="hidden" name="MAX_FILE_SIZE" value="2097152">
  <input type="file" name="file" accept="image/*">
  <button type="submit">上傳</button>
</form>

安全性關鍵點總結

遵循「不信任客戶端任何資料」原則,層層把關,才能確保上傳功能安全可靠。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
風險防護措施
惡意腳本上傳MIME + 副檔名雙重驗證、getimagesize、二次轉存、隨機檔名、儲存目錄禁用執行權限
檔名路徑遍歷不使用原始檔名、basename()、路徑正規化
大檔案耗盡磁碟upload_max_filesize、post_max_size、程式碼層面 $file['size'] 檢查
DoS 攻擊限流、驗證碼、非同步處理佇列