Laravel升级后Maatwebsite 3.1+jQuery/Ajax导出CSV报错处理
问题:Laravel Excel升级后Ajax导出CSV报错
升级Laravel及maatwebsite/excel包后,重构导出功能时出现错误:The Response content must be a string or object implementing __toString(), "object" given.
场景:用户通过选择日期、类型、客户后,点击导出按钮,用jQuery/Ajax提交请求。
解决方案
1. 修复控制器返回逻辑
控制器直接返回SaleJournalExport对象不符合Laravel响应规范,需使用Excel门面的download()方法生成正确的响应,并设置适配Ajax的响应头。
修改控制器代码:
use Maatwebsite\Excel\Facades\Excel; public function exportCSV(Request $request) { $data = $request->all(); $fileName = date('YmdHis-') . 'sale-journal.csv'; // 生成CSV文件响应 $response = Excel::download(new SaleJournalExport($data), $fileName, \Maatwebsite\Excel\Excel::CSV); // 设置响应头,确保Ajax能正确解析二进制数据 return $response->header('Content-Type', 'text/csv') ->header('Content-Disposition', "attachment; filename=\"{$fileName}\""); }
2. 修正SaleJournalExport的集合结构
原代码中$output[] = array_values($table1);会导致集合嵌套多余的数组层级,破坏CSV的行结构,需直接将每行数据添加到输出数组中。
修改SaleJournalExport构造函数中的销售数据处理部分:
// 移除原有的$table1变量,直接将行数据加入$output if ($sales) { foreach($sales as $index => $sale){ $number = ($sale->sale_tag == '0') ? 'SI-'.$sale->number : 'OR-'.$sale->number; $output[] = [ $sale->number, date('M d, Y',strtotime($sale->date_delivered)), $sale->document_reference, GlobalModel::getSingleDataTable('customers',$sale->customer_id)->name, $this->checkStatus($sale->status), ($sale->total_vat + $sale->total_net_of_vat), $sale->total_vat, $sale->total_net_of_vat, $sale->total_wht, $sale->total_amount_due ]; } } else { // 添加空行占位 $output[] = ["", "", "", "", "", "", "", "", "", ""]; }
确保collection()方法正确返回处理后的集合:
private $collection; public function __construct($data) { $output = []; // ... 其他标题、日期、表头、页脚逻辑保持不变 ... $this->collection = collect($output); } public function collection() { return $this->collection; }
3. 完善Ajax下载逻辑
原Ajax成功回调仅创建了ObjectURL,未触发实际下载动作,需添加创建临时a标签实现下载的逻辑,并清理资源。
修改JavaScript的success回调:
success: function(response, status, xhr) { if (response) { // 从响应头提取文件名 let contentDisposition = xhr.getResponseHeader('Content-Disposition'); let fileName = 'sale-journal.csv'; if (contentDisposition) { let matches = contentDisposition.match(/filename="?([^"]+)"?/); fileName = matches?.[1] || fileName; } // 触发下载 let src = window.URL.createObjectURL(response); let a = document.createElement('a'); a.href = src; a.download = fileName; document.body.appendChild(a); a.click(); // 清理资源 window.URL.revokeObjectURL(src); document.body.removeChild(a); swal.close(); } },
4. 额外检查项
- 确认maatwebsite/excel版本与Laravel版本兼容(Laravel 9+对应3.1+版本),配置文件已正确发布。
- 验证
checkStatus()方法返回值为字符串,避免非字符串类型导致CSV生成异常。 - 确保
GlobalModel::getSingleDataTable('customers',$sale->customer_id)能正确获取客户数据,防止调用->name时抛出错误。
内容的提问来源于stack exchange,提问作者Angel
相关产品推荐
相关产品推荐

