一、文件上傳核心變量 \$_FILES
$filename = $_FILES["myFile"]["name"]; // 原始文件名
$type = $_FILES["myFile"]["type"]; // MIME 類型
$tmp_name = $_FILES["myFile"]["tmp_name"]; // 臨時文件路徑
$size = $_FILES["myFile"]["size"]; // 文件大小(字節)
$error = $_FILES["myFile"]["error"]; // 錯誤代碼
二、移動臨時文件到目標目錄
// 推薦:move_uploaded_file() 會檢查文件是否通過 HTTP POST 上傳
move_uploaded_file($tmp_name, "D:/" . $filename);
// 替代:copy() 不做上傳驗證
copy($tmp_name, "D:/" . $filename);
三、php.ini 關鍵上傳配置
| 配置項 | 默認值 | 說明 |
| file_uploads | On | 是否允許 HTTP 文件上傳 |
| upload_tmp_dir | 系統臨時目錄 | 臨時文件存放路徑 |
| upload_max_filesize | 2M | 單文件最大值 |
| max_file_uploads | 20 | 單次最大文件數 |
| post_max_size | 8M | POST 數據總大小限制(需 > upload_max_filesize) |
| max_execution_time | 30 | 腳本最大執行秒數 |
| max_input_time | 60 | 解析輸入數據最大秒數 |
| memory_limit | 128M | 單線程內存限制 |
四、錯誤碼對照表
| 代碼 | 含義 |
| 0 | 上傳成功 |
| 1 | 超過 php.ini upload_max_filesize |
| 2 | 超過表單 MAX_FILE_SIZE |
| 3 | 文件部分上傳 |
| 4 | 無文件上傳 |
| 6 | 找不到臨時目錄 |
| 7 | 文件寫入失敗 |
| 8 | 被 PHP 擴展中斷 |
五、單文件上傳完整實例
form.html
<!doctype html>
<html><head><meta charset="UTF-8"><title>文件上傳</title></head><body>
<form action="fileUpload.php" method="post" enctype="multipart/form-data">
請選擇文件: <input type="file" name="myFile"><br>
<input type="submit" value="上傳">
<!-- 可選:客戶端限制 -->
<!-- <input type="hidden" name="MAX_FILE_SIZE" value="2097152"> -->
<!-- <input type="file" name="myFile" accept="image/jpeg,image/png,image/gif"> -->
</form>
</body></html>
fileUpload.php
<?php
header("Content-Type: text/html; charset=utf-8");
$fileInfo = $_FILES["myFile"];
$filename = $fileInfo["name"];
$type = $fileInfo["type"];
$error = $fileInfo["error"];
$size = $fileInfo["size"];
$tmp_name = $fileInfo["tmp_name"];
$maxSize = 2 * 1024 * 1024; // 2MB
$allowExt = ["jpeg", "jpg", "gif"]; // 允許擴展名
$flag = true; // 是否檢測真實圖片類型
if ($error === 0) {
// 文件大小檢查
if ($size > $maxSize) exit("上傳文件過大");
// 擴展名檢查
$ext = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
if (!in_array($ext, $allowExt)) exit("非法文件類型");
// 真實圖片類型檢測 (防偽裝)
if ($flag && !@getimagesize($tmp_name)) exit("非真實圖片類型");
// 目標目錄
$path = "D:/test/";
if (!file_exists($path)) {
mkdir($path, 0777, true);
chmod($path, 0777);
}
// 唯一文件名 (防覆蓋)
$uniName = md5(uniqid(microtime(true), true)) . "." . $ext;
$destination = $path . $uniName;
if (@move_uploaded_file($tmp_name, $destination)) {
echo "上傳成功:$uniName";
} else {
echo "上傳失敗";
}
} else {
$msg = ["", "超過服務器限制", "超過表單限制", "部分上傳", "無文件", "", "無臨時目錄", "寫入失敗", "擴展中斷"];
echo "上傳錯誤:" . ($msg[$error] ?? "未知錯誤");
}
最佳實踐提醒
- 雙重驗證:前端 JS 攔截 + 後端 PHP 嚴格校驗
- 類型檢測:不要信任 \$_FILES['type'],必須用
getimagesize() 或 finfo_file() 驗證
- 存儲安全:上傳目錄禁用腳本執行權限,文件重命名存儲
- 大文件分片:超大文件採用前端分片 + 後端合併策略