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

PHP 檔案上傳核心函數演進與實戰對比

     編輯:PHP 相關知識

上傳函數的歷史演進

PHP 檔案上傳核心函數經歷三個階段:早期 copy() + is_uploaded_file() 組合 → PHP 4.0.3+ 引入 move_uploaded_file() → 現代最佳實踐結合驗證、隨機命名、儲存抽象。理解演進脈絡有助於避開舊代碼陷阱。

三大核心函數解析

函數用途特點適用版本
copy(src, dest)複製任意檔案不驗證來源,可複製本地任意檔案,安全風險高所有版本
is_uploaded_file(filename)驗證是否為 HTTP POST 上傳需搭配 copy() 使用,兩步驟易漏驗證PHP 4.0.3+
move_uploaded_file(filename, dest)驗證並移動上傳檔案原子性驗證+移動,不可被繞過,現代標準做法PHP 4.0.3+

舊寫法 vs 新寫法對比

舊寫法(PHP 4.0.3 前)

<?php
$path = './uploadfiles/';
if (is_uploaded_file($filename)) {  // 注意:傳入 $filename 而非 $_FILES['filename']['name']
    $file1 = $_FILES['filename']['name'];
    $file2 = $path . time() . $file1;
    $flag = 1;
}
if ($flag) $result = copy($file1, $file2);  // 風險:$file1 可能被竄改為任意路徑
if ($result) echo '上傳成功!';
?>

新寫法(PHP 4.0.3+ 標準)

<?php
$path = './uploadfiles/';
if ($_FILES['filename']['name']) {
    $file1 = $_FILES['filename']['name'];
    $file2 = $path . time() . $file1;
    $flag = 1;
}
if ($flag) {
    // 關鍵:第一參數必須是 tmp_name(伺服器暫存路徑)
    $result = move_uploaded_file($_FILES['filename']['tmp_name'], $file2);
}
if ($result) echo '上傳成功!';
?>

關鍵差異與安全啟示

  1. 參數來源:move_uploaded_file 強制要求 tmp_name,確保操作的是伺服器管控的暫存檔,而非用戶可控的原始檔名
  2. 原子性:單一函數完成驗證與移動,消除 TOCTOU(檢查時刻到使用時刻)競態風險
  3. 不可繞過:copy() 可複製任意可讀檔案,配合路徑遍歷可讀取敏感檔;move_uploaded_file 內核層級驗證上傳來源

前端表單標準寫法

<form enctype="multipart/form-data" action="upload.php" method="post">
  <input type="file" name="filename">
  <input type="submit" value="送出檔案">
</form>

生產級上傳檢查清單

  • [ ] 使用 move_uploaded_file 而非 copy
  • [ ] 驗證 $_FILES['file']['error'] === UPLOAD_ERR_OK
  • [ ] MIME 白名單 + finfo_file() 二進位驗證
  • [ ] 副檔名白名單 + 隨機化檔名(bin2hex(random_bytes(16)))
  • [ ] 上傳目錄不可執行、置於 Webroot 外
  • [ ] 記錄上傳日誌(用戶、IP、時間、檔名、大小、MIME、結果)
  • [ ] 設定合理的 upload_max_filesize、post_max_size、memory_limit

從 copy() 到 move_uploaded_file() 的演進,體現 PHP 安全機制的成熟。現代開發應堅持使用最新標準 API,並建立多層防禦體系。

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