Laravel中如何实现一键导出两个Excel文件?(基于maatwebsite/excel)
解决同时导出两个Excel文件的问题
问题原因
你当前的代码无法实现需求的核心原因是:HTTP响应只能返回一个文件流。你的控制器返回了两个Excel::download()实例组成的数组,这不符合HTTP协议规范,浏览器只会忽略第二个文件,甚至可能直接返回错误。
最佳解决方案:打包成ZIP文件下载
最稳妥的方式是把两个Excel文件打包成一个ZIP压缩包,用户下载后解压就能得到两个文件。下面是具体实现步骤:
1. 确保服务器支持ZipArchive
首先确认你的PHP环境安装了ZipArchive扩展(大部分主流主机都默认支持,如果是本地环境,可能需要在php.ini中开启extension=zip)。
2. 修改控制器代码
更新SummaryController的exportPurchasing方法,逻辑是:生成两个Excel文件的临时副本 → 打包成ZIP → 返回ZIP下载响应 → 清理临时文件。
use Maatwebsite\Excel\Facades\Excel; use ZipArchive; use Illuminate\Support\Facades\Storage; use Illuminate\Http\Request; public function exportPurchasing(Request $request) { // 1. 定义临时文件存储路径 $purchasingFile = 'temp/RekapPurchasing.xlsx'; $checklistFile = 'temp/RekapChecklistWH.xlsx'; $zipFileName = 'PurchasingReports.zip'; $zipPath = storage_path('app/temp/' . $zipFileName); // 确保临时目录存在 if (!Storage::exists('temp')) { Storage::makeDirectory('temp'); } // 2. 将Excel文件保存到临时目录 Excel::store(new exportRekapPurchasing, $purchasingFile); Excel::store(new exportChecklistWH, $checklistFile); // 3. 创建并打包ZIP文件 $zip = new ZipArchive; if ($zip->open($zipPath, ZipArchive::CREATE | ZipArchive::OVERWRITE)) { // 添加文件到ZIP,第二个参数是ZIP内显示的文件名 $zip->addFile(storage_path('app/' . $purchasingFile), 'RekapPurchasing.xlsx'); $zip->addFile(storage_path('app/' . $checklistFile), 'RekapChecklistWH.xlsx'); $zip->close(); } // 4. 返回ZIP下载响应,同时设置下载后自动删除临时文件 $response = response()->download($zipPath, $zipFileName); $response->deleteFileAfterSend(true); // 清理临时Excel文件 Storage::delete([$purchasingFile, $checklistFile]); return $response; }
3. Blade视图无需修改
你的现有Blade表单代码可以保持不变,用户点击按钮后会下载包含两个Excel文件的ZIP包。
备选方案:前端触发两次下载(不推荐)
如果不想用ZIP打包,也可以让前端在点击按钮时触发两次GET请求,分别下载两个文件。但这种方式可能会被浏览器的弹出窗口拦截器阻止,用户体验较差:
修改Blade视图的按钮点击事件:
<button type="button" class="btn btn-primary" onclick="downloadBothFiles()"> <i class="fas fa-download"></i> Rekap Purchasing and Checklis WH </button> <script> function downloadBothFiles() { // 触发第一个文件下载 window.open("{{ route('exportSinglePurchasing') }}", '_blank'); // 延迟触发第二个文件下载,降低被拦截概率 setTimeout(() => { window.open("{{ route('exportSingleChecklist') }}", '_blank'); }, 500); } </script>
然后新增两个路由和控制器方法:
// 路由 Route::get('/exportSinglePurchasing', 'SummaryController@exportSinglePurchasing')->name('exportSinglePurchasing'); Route::get('/exportSingleChecklist', 'SummaryController@exportSingleChecklist')->name('exportSingleChecklist'); // 控制器方法 public function exportSinglePurchasing() { return Excel::download(new exportRekapPurchasing, 'RekapPurchasing.xlsx'); } public function exportSingleChecklist() { return Excel::download(new exportChecklistWH, 'RekapChecklistWH.xlsx'); }
总结
优先选择ZIP打包方案,它更符合HTTP规范,用户体验也更好,不会被浏览器拦截。
内容的提问来源于stack exchange,提问作者Muamar Humaidi
相关产品推荐
相关产品推荐

