Laravel结合AJAX批量生成文档仅输出1份的问题排查
问题原因
- 前端问题
- 重复绑定点击事件:你把
#generer的点击事件绑定在#numero_projet的change回调里,每次切换项目选项都会新增一次点击事件绑定,最终点一次按钮会触发多次AJAX请求 - 参数传递错误:你同时把ID数组拼到URL路径里,又在data里传了一次ids参数,GET请求下直接拼接数组会被隐式转为逗号分隔的字符串,后端拿到的不是数组格式
- 下载逻辑缺陷:AJAX请求本身无法直接触发浏览器多文件下载,就算后端生成了多份文件也没法通过单次AJAX返回给用户
- 重复绑定点击事件:你把
- 后端问题
- 没有遍历ID数组:你直接把收到的
ids数组作为单值传入where条件,查询只会返回第一个匹配的id_contrat,自然只生成1份文档 - 单返回值不符合批量需求:单次请求只能返回一个下载响应,无法同时返回多份文档
- 没有遍历ID数组:你直接把收到的
修正方案
前端修改
<script> $(document).ready(function () { // 提取id_projet为公共变量,避免重复绑定事件 let id_projet = ''; $('#numero_projet').change(function() { id_projet = $(this).find("option:selected").data("id"); }); // 点击事件单独绑定,全局仅绑定一次 $('#generer').click(function() { if (!id_projet) { alert('请先选择项目'); return; } let checkValues = []; $.each($("input[name='casting_checked']:checked"), function() { checkValues.push($(this).data('id')); }); if (checkValues.length === 0) { alert('请先勾选要生成的项'); return; } // 改用form提交触发下载,适配多文件打包场景 let form = $('<form method="post" action="generer"></form>'); form.append('<input type="hidden" name="_token" value="'+$('meta[name="csrf-token"]').attr('content')+'">'); form.append('<input type="hidden" name="id_projet" value="'+id_projet+'">'); // 数组参数加[]后缀适配Laravel参数解析规则 $.each(checkValues, function(i, id) { form.append('<input type="hidden" name="ids[]" value="'+id+'">'); }); $('body').append(form); form.submit(); form.remove(); }); }); </script>
后端修改(批量生成后打包为zip统一返回)
首先确保服务器已安装ziparchive扩展,再修改控制器代码:
public function generer(Request $request){ $id_projet = $request->input('id_projet'); $ids_casting = $request->input('ids'); // 初始化zip文件 $zip = new \ZipArchive(); $zipFileName = '合同批量导出_'.time().'.zip'; $zipFilePath = storage_path('app/public/temp/'.$zipFileName); // 自动创建临时目录 if (!file_exists(dirname($zipFilePath))) { mkdir(dirname($zipFilePath), 0755, true); } $zip->open($zipFilePath, \ZipArchive::CREATE | \ZipArchive::OVERWRITE); // 遍历所有选中的ID生成文档 foreach ($ids_casting as $id_casting) { $id_contrat = Projet_Casting::where('id_projet',$id_projet) ->where('id_casting',$id_casting) ->value('id_contrat'); $id_modele_contrat = Contrat::where('id_contrat',$id_contrat) ->value('id_modele_contrat'); $model_file = Model_Contrat::where('id_modele_contrat',$id_modele_contrat) ->value('fichier'); $templatePath = storage_path('app/public/uploads/modeles_contrat/'.$model_file); $templateProcessor = new \PhpOffice\PhpWord\TemplateProcessor($templatePath); $singleFileName = $id_contrat.'.docx'; $singleFilePath = storage_path('app/public/temp/'.$singleFileName); $templateProcessor->saveAs($singleFilePath); // 将单份文档加入压缩包 $zip->addFile($singleFilePath, $singleFileName); // 删除临时单文件 unlink($singleFilePath); } $zip->close(); // 返回zip下载,下载完成后自动删除服务端临时文件 return response()->download($zipFilePath)->deleteFileAfterSend(true); }
路由调整
删除原路由中路径携带ids的规则,改为POST请求接收参数即可。
内容的提问来源于stack exchange,提问作者saadia
相关产品推荐
相关产品推荐

