PHP多文件上传问题:分次上传仅提交最后一批图片如何解决?
解决PHP分次多文件上传只保留最后一批的问题
兄弟,我懂你这个痛点!原生的<input type="file" multiple>确实有个坑——每次你选新文件时,浏览器会自动清空之前选中的文件列表,所以提交的时候只会发送最后一次选的那批,之前的都没带上。要实现分次选择后一次性提交所有文件,得靠前端JS来帮忙维护文件列表,再结合后端正常处理就行。
核心思路
用JavaScript把用户每次选中的文件都存到一个数组里,提交时把数组里的所有文件通过FormData一起发给后端,这样后端就能拿到所有分次选择的文件了。
具体实现代码
1. 前端HTML+JavaScript
先改一下前端结构,加个显示已选文件的区域,再用JS维护文件数组:
<!-- 文件选择框 --> <input type="file" name="file[]" id="file" multiple> <!-- 显示已选文件列表 --> <div id="selected-files" style="margin: 10px 0;"></div> <!-- 自定义提交按钮 --> <button type="button" id="submit-btn">提交所有文件</button>
// 用来存储所有分次选中的文件 let allSelectedFiles = []; // 监听文件选择事件 document.getElementById('file').addEventListener('change', function(e) { // 把本次选中的文件转成数组 const newFiles = Array.from(e.target.files); // 合并到总文件数组里 allSelectedFiles = [...allSelectedFiles, ...newFiles]; // 更新页面上的已选文件显示 const fileListEl = document.getElementById('selected-files'); fileListEl.innerHTML = ''; allSelectedFiles.forEach((file, index) => { const fileItem = document.createElement('div'); fileItem.textContent = `${index + 1}. ${file.name} (${(file.size / 1024).toFixed(2)}KB)`; fileListEl.appendChild(fileItem); }); }); // 监听提交按钮点击事件 document.getElementById('submit-btn').addEventListener('click', function() { if (allSelectedFiles.length === 0) { alert('还没选任何文件呢!'); return; } // 创建FormData对象,用来装所有文件 const formData = new FormData(); // 把所有文件添加到FormData里 allSelectedFiles.forEach(file => { formData.append('file[]', file); }); // 用AJAX发送请求到后端 fetch('你的控制器路径.php', { method: 'POST', body: formData }) .then(res => res.text()) .then(result => { alert('所有文件上传成功!'); console.log('后端返回结果:', result); // 清空已选文件列表和输入框 allSelectedFiles = []; document.getElementById('selected-files').innerHTML = ''; document.getElementById('file').value = ''; }) .catch(err => { console.error('上传出错:', err); alert('上传失败,请重试'); }); });
2. 后端PHP处理
你的原有代码基础上稍微完善一下,就能处理所有上传的文件了:
<?php if ($_SERVER['REQUEST_METHOD'] === 'POST') { // 检查是否有文件上传 if (isset($_FILES['file']) && !empty($_FILES['file']['name'][0])) { $totalFiles = count($_FILES['file']['name']); echo "总共收到 $totalFiles 个文件<br>"; // 上传目录(确保有写入权限) $uploadDir = './uploads/'; if (!is_dir($uploadDir)) { mkdir($uploadDir, 0777, true); } // 逐个处理文件 for ($i = 0; $i < $totalFiles; $i++) { $fileName = $_FILES['file']['name'][$i]; $tmpFilePath = $_FILES['file']['tmp_name'][$i]; $fileError = $_FILES['file']['error'][$i]; // 检查文件上传是否成功 if ($fileError === UPLOAD_ERR_OK) { // 可以在这里加文件类型、大小的验证逻辑 $destPath = $uploadDir . basename($fileName); if (move_uploaded_file($tmpFilePath, $destPath)) { echo "文件「$fileName」上传成功,路径:$destPath<br>"; } else { echo "文件「$fileName」移动失败<br>"; } } else { echo "文件「$fileName」上传出错,错误码:$fileError<br>"; } } } else { echo '没有收到任何文件'; } } ?>
为什么原来的方法不行?
原生的multiple文件输入框,每次触发change事件时,都会替换掉内部的文件列表,而不是追加。所以你分次选文件时,之前的文件其实已经被浏览器丢弃了,提交自然只有最后一批。用JS维护数组的方式,相当于把每次选的文件都“存起来”,最后一起发送,完美解决这个问题。
内容的提问来源于stack exchange,提问作者Thisaru
相关产品推荐
相关产品推荐

