文件上傳核心流程
- 判斷是否有文件上傳(
$_FILES['myfile']['name'] != '')
- 檢查上傳錯誤碼(
$_FILES['myfile']['error'])
- 驗證文件類型、大小等業務規則
- 檢查目標目錄是否存在同名文件
- 使用
move_uploaded_file() 將臨時文件移動到永久目錄
關鍵 $_FILES 字段詳解
| 鍵名 | 說明 |
| name | 客戶端原始文件名 |
| type | MIME 類型(瀏覽器提供,不可完全信任) |
| size | 文件大小(位元組) |
| tmp_name | 服務端臨時存儲路徑,腳本結束後自動刪除 |
| error | 錯誤代碼(0 表示成功) |
HTML 表單必要屬性
<form action="upload.php" method="post" enctype="multipart/form-data">
<input type="file" name="myfile" />
<input type="submit" value="上傳" />
</form>
method="post":文件必須用 POST 傳輸
enctype="multipart/form-data":指定編碼方式,否則 $_FILES 為空
進階上傳處理範例
1. 限制文件大小與類型
$maxSize = 2 * 1024 * 1024; // 2MB
$allowedTypes = ['image/jpeg', 'image/pjpeg'];
if ($_FILES['myfile']['size'] > $maxSize) {
exit('文件不能大於 2MB');
}
if (!in_array($_FILES['myfile']['type'], $allowedTypes)) {
exit('只允許 JPG 格式');
}
2. 防止文件名衝突:隨機重命名
$ext = pathinfo($_FILES['myfile']['name'], PATHINFO_EXTENSION);
$newName = time() . rand(1000, 9999) . '.' . $ext;
3. 按用戶隔離存儲目錄
$userDir = $_SERVER['DOCUMENT_ROOT'] . "/uploads/{$username}/";
if (!is_dir($userDir)) {
mkdir($userDir, 0755, true);
}
$destPath = $userDir . $newName;
4. 移動文件並處理中文文件名編碼
if (move_uploaded_file($_FILES['myfile']['tmp_name'], iconv('UTF-8', 'GBK', $destPath))) {
echo '上傳成功';
} else {
echo '上傳失敗';
}
完整處理腳本 uploadProcess.php
<?php
$username = $_POST['username'];
$fileIntro = $_POST['fileintro'];
// 基礎驗證
if ($_FILES['myfile']['error'] !== UPLOAD_ERR_OK) {
exit('上傳錯誤:' . $_FILES['myfile']['error']);
}
if ($_FILES['myfile']['size'] > 2 * 1024 * 1024) {
exit('文件超過 2MB 限制');
}
$allowed = ['image/jpeg', 'image/png', 'image/gif'];
if (!in_array($_FILES['myfile']['type'], $allowed)) {
exit('不支持的文件類型');
}
// 目標路徑
$ext = strtolower(pathinfo($_FILES['myfile']['name'], PATHINFO_EXTENSION));
$newName = uniqid('img_', true) . ".{$ext}";
$userDir = $_SERVER['DOCUMENT_ROOT'] . "/uploads/{$username}/";
if (!is_dir($userDir)) mkdir($userDir, 0755, true);
$dest = $userDir . $newName;
// 移動文件
if (move_uploaded_file($_FILES['myfile']['tmp_name'], $dest)) {
// 這裡可寫入數據庫記錄:用戶、文件路徑、介紹等
echo "{$_FILES['myfile']['name']} 上傳成功";
} else {
echo '上傳失敗,請檢查目錄權限';
}
?>
安全加固建議
- 不要信任 $_FILES['type'],使用
finfo_file() 或 getimagesize() 二次驗證真實類型。
- 上傳目錄設置為 不可執行腳本(Nginx/Apache 禁用 PHP 解析)。
- 文件名存入資料庫時使用隨機名,原始名僅作展示。
- 限制上傳總數、頻率,防止磁碟耗盡。
- 定期掃描上傳目錄清理孤兒文件。