文件上傳是 Web 開發高頻需求,涉及前端表單、$_FILES 超全局變量、安全驗證、臨時文件移動等多個環節。本文通過 3 個 Demo 構建完整上傳流程。
<form enctype="multipart/form-data" action="Demo2.php" method="post">
<input type="hidden" name="MAX_FILE_SIZE" value="2000000" />
上傳文件: <input type="file" name="userfile" />
<input type="submit" value="上傳" />
</form>
關鍵點:enctype="multipart/form-data" 必須設置;隱藏域 MAX_FILE_SIZE 為客戶端提示(瀏覽器不強制執行)。
Array
(
[userfile] => Array
(
[name] => 原始文件名
[type] => MIME類型 (如 image/jpeg)
[tmp_name] => 臨時存儲路徑 (如 C:\Windows\Temp\phpXXXX.tmp)
[error] => 錯誤碼 (0=成功)
[size] => 文件大小(字節)
)
)
// 允許的 MIME 類型
$allowedMimes = ['image/jpeg','image/pjpeg','image/gif','image/png','image/x-png'];
// 1. 類型驗證
if (!in_array($_FILES['userfile']['type'], $allowedMimes)) {
exit('只允許 jpg/png/gif 圖片');
}
// 2. 上傳錯誤碼檢查
if ($_FILES['userfile']['error'] > 0) {
$msg = ['','超過 php.ini 上傳限制','超過表單 MAX_FILE_SIZE','部分上傳','未上傳'];
exit($msg[$_FILES['userfile']['error']]);
}
// 3. 文件大小限制 (2MB)
if ($_FILES['userfile']['size'] > 2000000) {
exit('文件不得超過 2MB');
}
// 4. 臨時文件存在性驗證
if (!is_uploaded_file($_FILES['userfile']['tmp_name'])) {
exit('臨時文件不存在');
}
$uploadDir = __DIR__ . '/uploads';
if (!is_dir($uploadDir)) {
mkdir($uploadDir, 0777, true);
}
$dest = $uploadDir . '/' . $_FILES['userfile']['name'];
if (!move_uploaded_file($_FILES['userfile']['tmp_name'], $dest)) {
exit('移動失敗,請檢查目錄權限');
}
// 成功跳轉顯示
header("Location: Demo3.php?url=" . urlencode($_FILES['userfile']['name']));
$url = $_GET['url']; echo "<img src='uploads/" . htmlspecialchars($url) . "'/>";
finfo_file() 檢測真實 MIME,防偽裝。uniqid().'.'.pathinfo($name, PATHINFO_EXTENSION),防覆蓋與路徑遍歷。location /uploads { php_flag engine off; }。| 錯誤碼 | 常量 | 含義 |
|---|---|---|
| 1 | UPLOAD_ERR_INI_SIZE | 超過 php.ini upload_max_filesize |
| 2 | UPLOAD_ERR_FORM_SIZE | 超過表單 MAX_FILE_SIZE |
| 3 | UPLOAD_ERR_PARTIAL | 部分上傳 |
| 4 | UPLOAD_ERR_NO_FILE | 未選擇文件 |
| 6 | UPLOAD_ERR_NO_TMP_DIR | 缺少臨時目錄 |
| 7 | UPLOAD_ERR_CANT_WRITE | 寫入失敗 |
| 8 | UPLOAD_ERR_EXTENSION | 擴展中斷上傳 |