完整代碼 (upload.php)
<?php
if ($_GET['action'] ?? '' === 'upfile') {
$target = 'temp_' . basename($_FILES['photo']['name']);
echo '臨時檔: ' . $_FILES['photo']['tmp_name'] . '<br>';
echo '目標檔: ' . $target . '<br>';
// 核心上傳邏輯
if (move_uploaded_file($_FILES['photo']['tmp_name'], $target)) {
// 非 Windows 設定權限
if (PHP_OS_FAMILY !== 'Windows') @chmod($target, 0644);
echo '<font color="green">上傳成功</font><br>';
echo '<a href="' . $target . '"><img src="' . $target . '" border="0"></a>';
} else {
echo '<font color="red">上傳失敗</font>';
}
exit;
}
?>
<!DOCTYPE html>
<html><head><title>PHP 圖片上傳範例</title></head><body>
<h1>圖片上傳</h1>
<form action="upload.php?action=upfile" method="post" enctype="multipart/form-data">
<input type="file" name="photo" accept="image/*" required>
<button type="submit">上傳</button>
</form>
</body></html>
關鍵要點
enctype="multipart/form-data" 表單屬性必須設置,否則 $_FILES 為空。
- 使用
basename() 取得檔名,防止路徑遍歷攻擊。
move_uploaded_file() 會檢查檔案是否為真正上傳檔,比 copy() 更安全。
- 生產環境必須加入:檔案類型驗證(MIME + 副檔名)、大小限制、隨機重命名、儲存至非 Web 可執行目錄、資料庫記錄元資料等。
進階安全檢查清單
getimagesize() 確認圖片真偽。
finfo_file() 檢測真實 MIME 類型。
- 檔名採用
uniqid() . '_' . hash('sha256', $content) 避免衝突與覆蓋。
- 上傳目錄設置
open_basedir 限制、Nginx/Apache 禁用腳本執行權限。