You need to enable JavaScript to run this app. Laravel结合AJAX批量生成文档仅输出1份的问题排查
优惠活动
大模型
产品
解决方案
定价
更多

Laravel结合AJAX批量生成文档仅输出1份的问题排查

问题原因

  • 前端问题
    1. 重复绑定点击事件:你把#generer的点击事件绑定在#numero_projet的change回调里,每次切换项目选项都会新增一次点击事件绑定,最终点一次按钮会触发多次AJAX请求
    2. 参数传递错误:你同时把ID数组拼到URL路径里,又在data里传了一次ids参数,GET请求下直接拼接数组会被隐式转为逗号分隔的字符串,后端拿到的不是数组格式
    3. 下载逻辑缺陷:AJAX请求本身无法直接触发浏览器多文件下载,就算后端生成了多份文件也没法通过单次AJAX返回给用户
  • 后端问题
    1. 没有遍历ID数组:你直接把收到的ids数组作为单值传入where条件,查询只会返回第一个匹配的id_contrat,自然只生成1份文档
    2. 单返回值不符合批量需求:单次请求只能返回一个下载响应,无法同时返回多份文档

修正方案

前端修改

<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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.11 08:42:01