批量上傳是電商後台、相簿系統、CMS 等專案的高頻需求。本文將從前端表單結構、PHP 後端處理邏輯、安全性考量三個層面,完整呈現一個可直接落地的批量圖片上傳方案。
<form action="upload.php" method="post" enctype="multipart/form-data">
<!--
1. name 陣列寫法 pictures[],PHP 會自動組成 $_FILES['pictures'] 多維陣列
2. multiple 屬性可讓用戶一次選多檔(HTML5)
-->
<input type="file" name="pictures[]" multiple accept="image/*">
<button type="submit" name="upload">開始上傳</button>
</form>
<?php
// upload.php
if (isset($_POST['upload'])) {
// 1. 目標資料夾
$destFolder = __DIR__ . '/uploads/pictures/';
if (!is_dir($destFolder)) {
mkdir($destFolder, 0755, true); // 遞迴建立,權限 0755
}
// 2. 遍歷上傳檔案陣列
$files = $_FILES['pictures'];
$uploaded = [];
$errors = [];
// $_FILES 結構:['name'][0], ['type'][0], ['tmp_name'][0], ['error'][0], ['size'][0]
$count = count($files['name']);
for ($i = 0; $i < $count; $i++) {
// 跳過空檔案欄位
if ($files['error'][$i] === UPLOAD_ERR_NO_FILE) continue;
// 3. 錯誤碼檢查
if ($files['error'][$i] !== UPLOAD_ERR_OK) {
$errors[] = "檔案 {$files['name'][$i]} 上傳失敗,錯誤碼:{$files['error'][$i]}";
continue;
}
// 4. 基礎驗證(生產環境請擴充:MIME 偵測、副檔名白名單、檔案大小、圖片尺寸等)
$allowedMimes = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'];
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime = finfo_file($finfo, $files['tmp_name'][$i]);
finfo_close($finfo);
if (!in_array($mime, $allowedMimes, true)) {
$errors[] = "檔案 {$files['name'][$i]} 類型不允許(僅支援 JPG/PNG/GIF/WebP)";
continue;
}
// 5. 產生唯一檔名,避免覆蓋與特殊字元問題
$ext = pathinfo($files['name'][$i], PATHINFO_EXTENSION);
$newName = bin2hex(random_bytes(16)) . '.' . strtolower($ext);
$destPath = $destFolder . $newName;
// 6. 移動暫存檔到正式位置
if (move_uploaded_file($files['tmp_name'][$i], $destPath)) {
$uploaded[] = [
'original' => $files['name'][$i],
'saved' => $newName,
'path' => $destPath,
'size' => $files['size'][$i],
'mime' => $mime,
];
} else {
$errors[] = "檔案 {$files['name'][$i]} 移動失敗(權限或磁碟空間不足)";
}
}
// 7. 回傳結果(AJAX 可用 JSON,傳統表單可存 Session 導向結果頁)
header('Content-Type: application/json; charset=utf-8');
echo json_encode([
'success' => empty($errors),
'uploaded' => $uploaded,
'errors' => $errors,
], JSON_UNESCAPED_UNICODE);
exit;
}
?>
| 維度 | 建議措施 |
|---|---|
| 檔案驗證 | 使用 finfo 偵測真實 MIME,勿信任 $_FILES['type'](客戶端可偽造) |
| 檔名安全 | 隨機雜湊 + 副檔名;資料庫另存原始檔名供下載顯示 |
| 大小限制 | PHP upload_max_filesize、post_max_size;前端 JS 預檢 |
| 圖片處理 | 上傳後用 GD/Imagick 壓縮、生成縮圖、剝離 EXIF(隱私) |
| 儲存架構 | 大量檔案建議雲端儲存或分散式檔案系統,資料庫只存路徑 |
| 防禦措施 | 上傳目錄禁用腳本執行權限、掃毒、防熱連結 |
傳統表單提交會跳轉頁面,現代專案多採用 FormData + fetch/XHR 非同步上傳,並監聽 progress 事件顯示進度條:
const formData = new FormData();
document.querySelector('input[name="pictures[]"]').files.forEach(f =>
formData.append('pictures[]', f)
);
fetch('upload.php', { method: 'POST', body: formData })
.then(r => r.json())
.then(data => console.log('上傳完成', data));
批量上傳核心在於:表單 name="files[]" + enctype="multipart/form-data" → PHP 遍歷 $_FILES 多維陣列 → 嚴格驗證 → 安全重命名 → move_uploaded_file 落地。配合前端 AJAX 與後端雲端儲存,即可構建企業級上傳系統。