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

PHP 文件上傳完整實現:從表單構建到安全驗證與移動存儲

     編輯:PHP 相關知識

核心流程

  1. HTML 表單設置 enctype="multipart/form-data"、method="post"。
  2. PHP 通過 $_FILES 超全局變量獲取上傳文件元數據。
  3. 驗證:is_uploaded_file() 確認合法上傳、MIME 類型白名單、文件大小限制、錯誤碼檢查。
  4. 安全存儲:move_uploaded_file() 將臨時文件移動至不可直接訪問的目錄,重命名防覆蓋。
  5. 回饋結果:JSON 或頁面提示成功/失敗原因。

完整代碼示例

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

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

$response = ['success' => false, 'message' => '', 'file' => null];

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

    // 1. 檢查上傳錯誤
    if ($file['error'] !== UPLOAD_ERR_OK) {
        $response['message'] = '上傳錯誤代碼: ' . $file['error'];
    }
    // 2. 驗證 MIME 類型 (需配合 finfo 擴展防偽裝)
    elseif (!in_array($file['type'], $allowedTypes)) {
        $response['message'] = '不允許的文件類型: ' . $file['type'];
    }
    // 3. 驗證大小
    elseif ($file['size'] > $maxSize) {
        $response['message'] = '文件過大,限制 ' . ($maxSize/1024/1024) . 'MB';
    }
    // 4. 合法性檢查
    elseif (!is_uploaded_file($file['tmp_name'])) {
        $response['message'] = '非法上傳文件';
    }
    else {
        // 5. 生成唯一文件名 防覆蓋
        $ext = pathinfo($file['name'], PATHINFO_EXTENSION);
        $newName = bin2hex(random_bytes(16)) . '.' . strtolower($ext);
        $destPath = $uploadDir . $newName;

        // 6. 移動文件
        if (move_uploaded_file($file['tmp_name'], $destPath)) {
            $response['success'] = true;
            $response['message'] = '上傳成功';
            $response['file'] = ['name' => $file['name'], 'path' => $newName, 'size' => $file['size']];
        } else {
            $response['message'] = '文件移動失敗,請檢查目錄權限';
        }
    }
}

// 輸出 JSON 供前端 AJAX 使用
header('Content-Type: application/json');
echo json_encode($response);
?>

<!-- HTML 表單 -->
<form action="upload.php" method="post" enctype="multipart/form-data" id="uploadForm">
  <input type="file" name="uploadfile" accept="image/*" required>
  <button type="submit">上傳</button>
</form>

<script>
// 可選:AJAX 無刷新上傳
document.getElementById('uploadForm').addEventListener('submit', async (e) => {
  e.preventDefault();
  const formData = new FormData(e.target);
  const res = await fetch('upload.php', {method: 'POST', body: formData}).then(r => r.json());
  alert(res.message);
  if (res.success) console.log('文件路徑:', res.file.path);
});
</script>

關鍵安全點總結

  • 類型驗證:不要只信任 $_FILES['type'],使用 finfo_file() 檢測真實 MIME。
  • 存儲路徑:上傳目錄置於 Web 根目錄外,或配置 Nginx/Apache 禁止腳本執行 (location ~ \.php$ { deny all; })。
  • 文件名:隨機重命名 + 保留副檔名,避免中文文件名編碼問題與覆蓋風險。
  • 大小限制:同時設置 PHP upload_max_filesize、post_max_size 及前端 MAX_FILE_SIZE 隱藏域(僅作用戶提示)。
  • 圖片二次渲染:對圖片使用 GD/Imagick 重新壓縮儲存,剝離潛在惡意代碼。

詳細說明:https://php.662p.com/thread-570-1-1.html

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved