現代 Web 文件上傳標準方案:HTML5 FormData + XMLHttpRequest Level 2 實現無刷新上傳、原生進度條、PHP 後端處理、大文件配置優化、安全驗證最佳實踐、多文件/拖拽擴展基礎。
無刷新上傳 無刷新文件上傳
'超過 php.ini upload_max_filesize',
UPLOAD_ERR_FORM_SIZE => '超過表單 MAX_FILE_SIZE',
UPLOAD_ERR_PARTIAL => '部分上傳',
UPLOAD_ERR_NO_FILE => '未選擇文件',
UPLOAD_ERR_NO_TMP_DIR => '臨時目錄不存在',
UPLOAD_ERR_CANT_WRITE => '寫入失敗',
UPLOAD_ERR_EXTENSION => '擴展中斷',
];
die('上傳錯誤: ' . ($errors[$error] ?? '未知錯誤'));
}
// 安全:驗證 MIME 類型 (防偽裝)
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime = finfo_file($finfo, $tmpName);
$allowed = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'];
if (!in_array($mime, $allowed)) {
die('不允許的文件類型: ' . $mime);
}
// 安全:生成隨機檔名防覆蓋/注入
$ext = pathinfo($originName, PATHINFO_EXTENSION);
$newName = uniqid('upload_', true) . '.' . $ext;
$dest = $uploadDir . $newName;
if (move_uploaded_file($tmpName, $dest)) {
echo "上傳成功! 文件: $newName";
// 可返回 JSON 供前端解析: echo json_encode(['url' => '/upload/' . $newName]);
} else {
echo "上傳失敗: 移動文件錯誤";
}
?>
| 配置項 | 建議值 | 說明 |
|---|---|---|
| upload_max_filesize | 100M | 單文件最大值 |
| post_max_size | 100M | POST 總體大小,需 ≥ upload_max_filesize |
| max_execution_time | 300 | 腳本最大執行秒數 |
| max_input_time | 300 | 解析輸入數據最大秒數 |
| memory_limit | 256M | PHP 記憶體限制 |
| Nginx client_max_body_size | 100M | Nginx 層面限制 |
修改 php.ini 後重啟 PHP-FPM/Apache;Nginx 修改 nginx.conf 重載。
tmp_name,move_uploaded_file 後無需手動刪finfo_file 而非信任 $_FILES['type'] (客戶端可偽造)uniqid() / hash() 防覆蓋、防路徑穿透0755、不可執行、Nginx location ~ \.php$ { deny all; } 禁用腳本執行getimagesize() 驗證真實圖片、imagecreatefromstring() 重編碼剝離 EXIF/腳本input[multiple] + drop 事件