多文件上传后PHP接收数组结构不符预期,求问题排查
多文件上传后PHP接收的文件数组结构不符合预期
我尝试用以下代码实现多文件上传:
<input type="file" class="file-upload-field" id="file_name" name="files_names[]" multiple="multiple" />
我的JavaScript/jQuery代码如下:
$(document).on('submit', '#addform', (function() { var files = $('#file_name')[0].files; var formData = new FormData(); for (var i=0; i < files.length; i++) formData.append('file_names[]', files[i]); $.ajax({ url: 'ajax_addrecord.php', type: "POST", data: formData, contentType: false, cache: false, processData:false, timeout: 2000, success: function(data) { console.log('Record added.'); } }); }));
但在PHP文件中通过以下代码检查文件接收情况时:
error_log($date_time." :: ".print_r($_FILES, true), 0);
得到的结果为:
2024-03-03 11:14:47 :: Array ( [file_names] => Array ( [name] => Array ( [0] => HeleneBarrow Profil.png [1] => horn_fuuuck_lovers.JPG [2] => lakn_profil_mona.JPG ) [type] => Array ( [0] => image/png [1] => image/jpeg [2] => image/jpeg ) [tmp_name] => Array ( [0] => /tmp/phpZ3FVIl [1] => /tmp/phpvolre9 [2] => /tmp/phpp4gYJW ) [error] => Array ( [0] => 0 [1] => 0 [2] => 0 ) [size] => Array ( [0] => 270198 [1] => 12359 [2] => 82773 ) )
而我预期的结果应该是每个文件对应一个独立数组:
[file_names] => Array [0] => Array ( [name] => HeleneBarrow Profil.png [type] => image/png [tmp_name] => /tmp/phpNmM8Se [error] => 0 [size] => 270198 ) [1] => Array ( [name] => horn_fuuuck_lovers.JPG [type] => image/jpeg [tmp_name] => /tmp/phpvolre9 [error] => 0 [size] => 270198 ) [2] => Array ( [name] => lakn_profil_mona.JPG [type] => image/jpeg [tmp_name] => /tmp/phpp4gYJW [error] => 0 [size] => 270198 )
目前数组是按属性而非文件进行分组的,请问哪里出了问题?
问题原因与解决办法
原因
这是PHP解析多文件上传数据的默认行为:当通过file_names[]格式提交多个文件时,PHP会自动将同一属性(name、type等)归组到子数组中,而非按单个文件打包成独立数组。
解决办法
有两种方式可以得到你预期的数组结构:
方式1:修改JavaScript中的FormData追加逻辑
在循环中给每个文件指定带索引的键名,替代file_names[]:
for (var i=0; i < files.length; i++) { // 直接用带索引的键名追加文件即可 formData.append(`file_names[${i}]`, files[i]); }
这样PHP会自动将每个文件解析为独立的数组元素,完全符合你的预期结构。
方式2:在PHP中转换现有数组结构
如果无法修改前端代码,可以在PHP里手动转换数组格式:
$formattedFiles = []; if (isset($_FILES['file_names'])) { $fileCount = count($_FILES['file_names']['name']); for ($i = 0; $i < $fileCount; $i++) { $formattedFiles['file_names'][$i] = [ 'name' => $_FILES['file_names']['name'][$i], 'type' => $_FILES['file_names']['type'][$i], 'tmp_name' => $_FILES['file_names']['tmp_name'][$i], 'error' => $_FILES['file_names']['error'][$i], 'size' => $_FILES['file_names']['size'][$i] ]; } } // 此时$formattedFiles就是你需要的按文件分组的结构
说明
两种方式都能实现目标,优先推荐修改前端代码的方式,它让数据传递更直接,减少后端的额外处理;如果前端代码无法调整,PHP转换的方式也能完美解决问题。
内容的提问来源于stack exchange,提问作者osomanden
相关产品推荐
相关产品推荐

