
本文详解如何通过 formdata 批量上传多个文件(如图片)至 php,并正确接收和处理,解决单文件限制与 `undefined index` 错误问题。
在 Web 开发中,实现多图上传是常见需求,但初学者常因 FormData 的键名约定和 PHP 的文件接收机制不匹配而失败。核心问题在于:JavaScript 传递多个文件时,必须使用带方括号的字段名(如 'images[]')以告知 PHP 将其解析为数组;而 PHP 端需遍历 $_FILES['images'] 的多维结构,而非直接访问 $_FILES['images'][0]。
✅ 正确的前端实现(JavaScript)
首先,确保 HTML 中 允许多选(添加 multiple 属性,你已做到):
关键修改在 JS:将 files(FileList 对象)逐个追加到 FormData,且字段名必须含 []:
const sampleImageInput = document.getElementById('images');
const submitBtn = document.getElementById('valider');
submitBtn.addEventListener('click', () => {
if (sampleImageInput.files.length === 0) {
alert('请先选择图片!');
return;
}
uploadImages(sampleImageInput.files); // 传入整个 FileList
});
const uploadImages = (files) => {
const formData = new FormData();
// 重要:使用 'images[]' 作为键名,PHP 才会识别为数组
for (let i = 0; i < files.length; i++) {
formData.append('images[]', files[i]);
}
fetch(host + 'add.php', {
method: 'POST',
body: formData
// ⚠️ 注意:不要设置 Content-Type!浏览器会自动设置 multipart/form-data 并携带正确 boundary
})
.then(response => response.json())
.then(data => {
console.log('上传成功:', data);
})
.catch(err => {
console.error('上传失败:', err);
});
};✅ 正确的后端处理(PHP)
PHP 接收的是一个标准化的多维数组结构(即使只传 1 张图,$_FILES['images'] 也包含 name, type, tmp_name, error, size 五个子数组)。因此不能直接 $_FILES['images'][0],而应按规范遍历:
立即学习“PHP免费学习笔记(深入)”;
'未收到任何文件']);
exit;
}
$uploadDir = __DIR__ . '/uploads/';
if (!is_dir($uploadDir)) {
mkdir($uploadDir, 0755, true);
}
$uploadedFiles = [];
$errors = [];
// 遍历每个上传的文件(注意:索引是 $_FILES['images']['name'][$i])
for ($i = 0; $i < count($_FILES['images']['name']); $i++) {
$name = $_FILES['images']['name'][$i];
$tmpName = $_FILES['images']['tmp_name'][$i];
$size = $_FILES['images']['size'][$i];
$error = $_FILES['images']['error'][$i];
$type = $_FILES['images']['type'][$i];
if ($error === UPLOAD_ERR_OK && $size > 0) {
$filePath = $uploadDir . basename($name);
if (move_uploaded_file($tmpName, $filePath)) {
$uploadedFiles[] = [
'name' => $name,
'size' => $size,
'type' => $type,
'path' => $filePath
];
} else {
$errors[] = "文件 {$name} 保存失败";
}
} else {
$errors[] = "文件 {$name} 上传错误:代码 {$error}";
}
}
// 统一返回结果
echo json_encode([
'success' => !empty($uploadedFiles),
'uploaded' => $uploadedFiles,
'errors' => $errors
], JSON_UNESCAPED_UNICODE);? 关键注意事项
- 字段名必须带 []:formData.append('images[]', file) 是强制约定,PHP 依赖此语法构建多维 $_FILES 数组。
- 不要手动设置 Content-Type:fetch 发送 FormData 时,若显式设置 headers: {'Content-Type': '...'},会破坏浏览器自动生成的 multipart/form-data; boundary=...,导致后端无法解析。
- PHP 的 $_FILES 结构是“转置”的:它不是 [{name, tmp_name, ...}],而是 ['name' => [...], 'tmp_name' => [...], ...],务必用 $i 索引统一访问各维度。
- 服务端安全校验不可少:实际项目中需验证 MIME 类型、文件扩展名、大小限制,并使用 getimagesize() 等函数防范恶意文件。
通过以上方案,即可稳定、高效地实现多图批量上传,兼顾兼容性与可维护性。











