如何将多个DataTable导出为PDF并打包成单个压缩文件夹
多DataTable批量导出PDF并打包为ZIP下载方案
问题背景
在分组报表系统中实现了多个隐藏渲染的DataTable,单表PDF下载通过触发对应按钮点击可正常工作:
let singlePDFdownload = function (table_id) { $(`.toolbar${table_id} .custom-pdf`).trigger('click') }
但实现批量下载时,直接触发所有.custom-pdf按钮的点击事件,会导致浏览器弹出多个下载窗口甚至触发安全警告,现有批量代码如下:
const $massPDFExport = $('#massPDFExport') $massPDFExport.on('click', () => { $(`.custom-pdf`).trigger('click') })
需要实现将所有DataTable的PDF导出文件合并为单个ZIP压缩包下载,避免多弹窗问题。以下是可复现的示例代码:
<link rel="stylesheet" href="https://cdn.datatables.net/1.13.4/css/jquery.dataTables.min.css"> <link rel="stylesheet" href="https://cdn.datatables.net/buttons/2.3.6/css/buttons.dataTables.min.css"> <script src="https://code.jquery.com/jquery-3.5.1.js"></script> <script src="https://cdn.datatables.net/1.13.4/js/jquery.dataTables.min.js"></script> <script src="https://cdn.datatables.net/buttons/2.3.6/js/dataTables.buttons.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.1.3/jszip.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.53/pdfmake.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.53/vfs_fonts.js"></script> <script src="https://cdn.datatables.net/buttons/2.3.6/js/buttons.html5.min.js"></script> <script src="https://cdn.datatables.net/buttons/2.3.6/js/buttons.print.min.js"></script> <script> $(document).ready(function () { $('#example_1').DataTable({ dom: 'Bfrtip', buttons: [ 'copy', 'csv', 'excel', 'pdf', 'print' ] }); $('#example_2').DataTable({ dom: 'Bfrtip', buttons: [ 'copy', 'csv', 'excel', 'pdf', 'print' ] }); $('#export_all').on('click', () => { $('.buttons-pdf').each(function (a) { console.log(9888) $(this).trigger("click"); }); }); }); </script> <a id='export_all' class=''> Export All As PDF</a> <table id="example_1" class="display nowrap" style="width:100%"> <thead> <tr> <th>Name</th> <th>Position</th> <th>Office</th> <th>Age</th> <th>Start date</th> <th>Salary</th> </tr> </thead> <tbody> <tr> <td>Tiger Nixon</td> <td>System Architect</td> <td>Edinburgh</td> <td>61</td> <td>2011-04-25</td> <td>$320,800</td> </tr> <tr> <td>Garrett Winters</td> <td>Accountant</td> <td>Tokyo</td> <td>63</td> <td>2011-07-25</td> <td>$170,750</td> </tr> </tbody> </table> <table id="example_2" class="display nowrap" style="width:100%"> <thead> <tr> <th>Name</th> <th>Position</th> <th>Office</th> <th>Age</th> <th>Start date</th> <th>Salary</th> </tr> </thead> <tbody> <tr> <td>Tiger Nixon</td> <td>System Architect</td> <td>Edinburgh</td> <td>61</td> <td>2011-04-25</td> <td>$320,800</td> </tr> <tr> <td>Garrett Winters</td> <td>Accountant</td> <td>Tokyo</td> <td>63</td> <td>2011-07-25</td> <td>$170,750</td> </tr> </tbody> </table>
解决方案
核心思路是绕过直接触发下载按钮的方式,主动获取每个DataTable的PDF生成数据,将其转换为Blob对象,再用JSZip将所有PDF文件打包为单个ZIP压缩包后下载。
修改后的完整代码
<link rel="stylesheet" href="https://cdn.datatables.net/1.13.4/css/jquery.dataTables.min.css"> <link rel="stylesheet" href="https://cdn.datatables.net/buttons/2.3.6/css/buttons.dataTables.min.css"> <script src="https://code.jquery.com/jquery-3.5.1.js"></script> <script src="https://cdn.datatables.net/1.13.4/js/jquery.dataTables.min.js"></script> <script src="https://cdn.datatables.net/buttons/2.3.6/js/dataTables.buttons.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.1.3/jszip.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.53/pdfmake.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.53/vfs_fonts.js"></script> <script src="https://cdn.datatables.net/buttons/2.3.6/js/buttons.html5.min.js"></script> <script src="https://cdn.datatables.net/buttons/2.3.6/js/buttons.print.min.js"></script> <script> $(document).ready(function () { // 初始化表格,保存表格实例 const table1 = $('#example_1').DataTable({ dom: 'Bfrtip', buttons: [ 'copy', 'csv', 'excel', 'pdf', 'print' ] }); const table2 = $('#example_2').DataTable({ dom: 'Bfrtip', buttons: [ 'copy', 'csv', 'excel', 'pdf', 'print' ] }); // 批量导出逻辑 $('#export_all').on('click', async () => { const zip = new JSZip(); const tables = [ { instance: table1, fileName: '报表1.pdf' }, { instance: table2, fileName: '报表2.pdf' } ]; // 遍历所有表格,生成PDF并添加到ZIP for (const tableInfo of tables) { const pdfBlob = await generateTablePDF(tableInfo.instance); zip.file(tableInfo.fileName, pdfBlob); } // 生成ZIP并下载 zip.generateAsync({ type: 'blob' }).then(function(content) { const link = document.createElement('a'); link.href = URL.createObjectURL(content); link.download = '所有报表.zip'; link.click(); URL.revokeObjectURL(link.href); }); }); // 生成单个表格的PDF Blob function generateTablePDF(tableInstance) { return new Promise((resolve) => { // 获取表格导出数据 const exportData = tableInstance.button(0).exportData(); // 构建PDF文档定义 const docDefinition = { content: [ { text: '报表数据', style: 'header' }, { table: { headerRows: 1, body: [exportData.header].concat(exportData.body) } } ], styles: { header: { fontSize: 16, bold: true, margin: [0, 0, 0, 10] } } }; // 生成PDF并转换为Blob pdfMake.createPdf(docDefinition).getBlob((blob) => { resolve(blob); }); }); } }); </script> <a id='export_all' class=''> Export All As PDF</a> <table id="example_1" class="display nowrap" style="width:100%"> <thead> <tr> <th>Name</th> <th>Position</th> <th>Office</th> <th>Age</th> <th>Start date</th> <th>Salary</th> </tr> </thead> <tbody> <tr> <td>Tiger Nixon</td> <td>System Architect</td> <td>Edinburgh</td> <td>61</td> <td>2011-04-25</td> <td>$320,800</td> </tr> <tr> <td>Garrett Winters</td> <td>Accountant</td> <td>Tokyo</td> <td>63</td> <td>2011-07-25</td> <td>$170,750</td> </tr> </tbody> </table> <table id="example_2" class="display nowrap" style="width:100%"> <thead> <tr> <th>Name</th> <th>Position</th> <th>Office</th> <th>Age</th> <th>Start date</th> <th>Salary</th> </tr> </thead> <tbody> <tr> <td>Tiger Nixon</td> <td>System Architect</td> <td>Edinburgh</td> <td>61</td> <td>2011-04-25</td> <td>$320,800</td> </tr> <tr> <td>Garrett Winters</td> <td>Accountant</td> <td>Tokyo</td> <td>63</td> <td>2011-07-25</td> <td>$170,750</td> </tr> </tbody> </table>
关键说明
- 保存表格实例:初始化DataTable时保存实例,方便后续调用导出API
- 自定义PDF生成:通过
exportData()获取表格的表头和数据,手动构建pdfmake的文档定义,生成PDF Blob而不是直接下载 - ZIP打包:使用JSZip将所有PDF Blob添加到压缩包,最后生成单个ZIP文件触发下载
- 异步处理:因为PDF生成是异步操作,使用
async/await确保所有PDF都生成完成后再打包
这种方式只会触发一次下载弹窗,完美解决多窗口和警告问题。
内容的提问来源于stack exchange,提问作者ViaTech
相关产品推荐
相关产品推荐

