如何将JavaScript构建的多文件数组通过AJAX正确传递至PHP的$_FILES数组
嘿,我仔细看了你的代码,问题的核心在于你处理FormData的方式不对。直接把整个fileArray数组通过form.append('file', fileArray)追加进去时,FormData不会自动把数组里的每个File对象解析成可上传的文件项,反而会把数组转换成字符串形式,这就导致PHP只能在$_POST里拿到这个字符串,而不是在$_FILES里收到上传的文件。
不同于使用multiple属性的单个文件输入,手动构建文件数组时必须显式地逐个处理每个File对象,FormData不会帮你自动批量解析数组里的文件。下面是具体的解决步骤:
第一步:修正JavaScript的FormData处理逻辑
你需要循环遍历fileArray,把每个File对象单独追加到FormData中,并且要把字段名设为file[](带方括号)——这个方括号是关键,它会告诉PHP这是一个多文件数组,从而正确把文件存入$_FILES。
同时,还要处理用户可能没在某个输入框选择文件的情况(避免把undefined追加进去),所以在收集文件和追加时都要加判断。修改后的submitFiles函数如下:
function submitFiles() { var table = document.getElementById('FileTable'); var fileArray = []; // 收集文件时先判断是否有选中文件 for (var r = 1, n = table.rows.length; r < n; r++) { var myInput = document.getElementById("myFileInput" + r); // 只有当用户选中了文件时才加入数组 if (myInput.files.length > 0) { fileArray.push(myInput.files[0]); } } var form = new FormData(), xhr = new XMLHttpRequest(); xhr.onreadystatechange = function() { if (xhr.readyState == XMLHttpRequest.DONE) { // 可以在这里查看PHP返回的响应,方便调试 console.log(xhr.responseText); alert('提交完成'); } } // 循环追加每个文件到FormData,字段名用file[] fileArray.forEach(file => { form.append('file[]', file); }); xhr.open('post', 'uploadMinReproduceable.php', true); xhr.send(form); }
第二步:PHP端正确接收并处理文件
现在文件会被正确传入$_FILES['file'],这是一个多维数组,包含所有上传文件的信息(比如文件名、临时路径、文件大小等)。你可以在PHP里这样调试或处理:
<?php header('Content-Type: application/json; charset=utf-8'); // 打印$_FILES的结构,方便查看 error_log('files params for upload file ' . $_SERVER['SCRIPT_NAME']); if (isset($_FILES['file'])) { foreach ($_FILES['file']['name'] as $index => $name) { error_log("文件{$index}:名称={$name},临时路径={$_FILES['file']['tmp_name'][$index]},大小={$_FILES['file']['size'][$index]}"); } } // 示例:将文件保存到服务器(需要确保uploads目录存在且有写入权限) // $uploadDir = 'uploads/'; // if (!is_dir($uploadDir)) mkdir($uploadDir, 0755, true); // foreach ($_FILES['file']['tmp_name'] as $index => $tmpPath) { // $targetPath = $uploadDir . $_FILES['file']['name'][$index]; // move_uploaded_file($tmpPath, $targetPath); // } ?>
为什么原来的方法不行?
当你执行form.append('file', fileArray)时,FormData会把数组fileArray转换成字符串"[object File],[object File],...",这个字符串会被当作普通的POST参数发送,自然就出现在PHP的$_POST['file']里,完全触发不了浏览器的文件上传机制,所以这些文件根本不会进入$_FILES数组。
备注:内容来源于stack exchange,提问作者Schwarz Software

