You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 08:40:08