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

PHP 簡易檔案上傳範例:從表單到安全儲存的完整流程

     編輯:PHP 相關知識

單一檔案完整範例 upload.php

<?php
// 1. 統一錯誤回應函數
function alert($msg) {
    return '<script>alert("' . addslashes($msg) . '");history.back();</script>';
}

// 2. 設定區
$allowType = ['image/jpeg', 'image/gif', 'image/png', 'image/webp'];
$filePath  = __DIR__ . '/uploadFileDir/';
$maxSize   = 102400; // 100KB

// 3. 接收檔案
$file = $_FILES['file'] ?? null;
if (!$file) exit(alert('未收到檔案'));

// 4. 檢查上傳錯誤碼
if ($file['error'] !== UPLOAD_ERR_OK) {
    exit(alert('上傳錯誤,代碼:' . $file['error']));
}

// 5. 檢查檔案大小
if ($file['size'] > $maxSize) {
    exit(alert('檔案過大,限制 100KB'));
}

// 6. 驗證真實 MIME 型別(比 $_FILES['type'] 可靠)
$finfo = new finfo(FILEINFO_MIME_TYPE);
$mime  = $finfo->file($file['tmp_name']);
if (!in_array($mime, $allowType, true)) {
    exit(alert('不支援的檔案類型:' . $mime));
}

// 7. 確保上傳目錄存在
if (!is_dir($filePath) && !mkdir($filePath, 0755, true)) {
    exit(alert('建立目錄失敗'));
}

// 8. 產生唯一檔名(避免覆蓋與安全風險)
$ext     = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
$newName = time() . '_' . bin2hex(random_bytes(8)) . '.' . $ext;
$dest    = $filePath . $newName;

// 9. 移動檔案
if (!move_uploaded_file($file['tmp_name'], $dest)) {
    exit(alert('儲存失敗,請稍後再試'));
}

// 10. 清理暫存檔(move_uploaded_file 成功後暫存檔會自動刪除,此行可省略)
// unlink($file['tmp_name']);

// 11. 成功回應
echo alert('恭喜,上傳檔案 [' . $newName . '] 成功!');
?>

對應的 HTML 表單

<!DOCTYPE html>
<html><head><meta charset="utf-8"><title>檔案上傳</title></head><body>
<form action="upload.php" method="post" enctype="multipart/form-data">
    <input type="file" name="file" accept="image/*" required>
    <button type="submit">上傳</button>
</form>
</body></html>

關鍵步驟解析

  1. 錯誤碼檢查:UPLOAD_ERR_OK (0) 表示成功,其他代碼請查閱官方文件
  2. MIME 型別驗證:使用 finfo 讀取檔案實際內容,防止偽裝副檔名
  3. 檔名重組:時間戳 + 隨機字串 + 原副檔名,防止覆蓋與路徑遍歷攻擊
  4. move_uploaded_file():唯一能確認檔案經由 HTTP POST 上傳的函數
  5. 目錄權限:0755 足夠,避免 0777

常見問題排查

現象可能原因解決方向
上傳大檔失敗php.ini upload_max_filesize/post_max_size 過小調整 php.ini 或 .user.ini
move_uploaded_file 回傳 false目標目錄權限不足、磁碟滿、open_basedir 限制檢查目錄擁有者/權限、磁碟空間
圖片上傳後無法顯示輸出前有 BOM/空白、Header 錯誤、路徑錯誤確保 PHP 檔案無 BOM、檢查輸出路徑
副檔名大寫導致驗證失敗未轉小寫比對strtolower(pathinfo(...))

進階擴充建議

  • 多檔上傳:name="files[]" + 迴圈處理 $_FILES['files']
  • 分塊上傳/斷點續傳:前端 Plupload/Uppy + 後端合併邏輯
  • 圖片壓縮/轉檔:搭配 GD/Imagick 處理
  • 雲端儲存:上傳至 S3/OSS 而非本地磁碟
  • 病毒掃描:整合 ClamAV 掃描暫存檔
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved