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

Laravel+InertiaJS导出Excel返回302无响应问题求助

Laravel 10 + InertiaJS + Laravel Excel导出返回302问题解决

问题描述

在Laravel 10项目中结合InertiaJS使用laravel-excel包实现Excel导出时,exportMPR接口始终返回302状态码且无文件下载响应。尝试过存储文件后获取、输出原始数据等方法,均未解决,期望实现直接文件下载或返回Blob数据。

核心原因

  1. InertiaJS请求的局限性:Inertia的表单请求(如post方法)是为JSON交互设计的,无法识别后端返回的文件下载响应(带Content-Disposition头),会将非JSON响应视为异常,触发框架内部逻辑导致302重定向。
  2. 认证中间件的判断逻辑:虽然认证中间件中写了$request->expectsJson() ? null : route('login'),但Inertia请求的Accept头并非application/json,导致expectsJson()返回false,一旦请求处理不符合预期,就会被重定向到登录页,出现302状态码。

解决方案

方式一:直接触发浏览器下载(推荐)

后端路由调整

将POST路由改为GET(下载场景用GET更符合REST规范):

// web.php
Route::middleware('auth')->group(function () {
    Route::controller(MPRController::class)->name('mpr.')->prefix('mpr')->group(function (): void {
        Route::get('export-mpr', 'exportMPR')->name('exportMPR');
    });
});

前端逻辑调整

替换原Inertia表单提交,用原生方式触发下载:

<script setup>
const downloadMPR = () => {
    const { year, monthIndex } = downloadMPRForm.yearMonth;
    // 拼接参数并打开新窗口下载
    window.open(`/mpr/export-mpr?year=${year}&month=${monthIndex}`, '_blank');
}
</script>

<template>
    <!-- 替换原表单按钮 -->
    <button type="button"
            class="text-white bg-blue-700 focus:outline-none font-medium rounded-lg text-sm px-5 py-2.5"
            :disabled="downloadMPRForm.processing"
            :class="{ 'opacity-25': downloadMPRForm.processing }"
            @click="downloadMPR">
        Submit
    </button>
</template>

方式二:返回Blob并手动触发下载(适用于必须用POST的场景)

后端控制器调整

生成Excel二进制数据并返回,设置正确响应头:

// MPRController.php
use Illuminate\Support\Facades\Response;
use Maatwebsite\Excel\Facades\Excel;

public function exportMPR()
{
    try {
        // 生成Excel原始内容
        $excelContent = Excel::raw(new MPRExport(request('month'), request('year')), \Maatwebsite\Excel\Excel::XLSX);
        
        // 返回二进制数据及下载头
        return Response::make($excelContent, 200, [
            'Content-Type' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
            'Content-Disposition' => 'attachment; filename="mpr.xlsx"',
        ]);
    } catch (Exception $e) {
        return response()->json(['error' => $e->getMessage()], 500);
    }
}

前端逻辑调整

用原生fetch处理Blob响应,手动触发下载:

<script setup>
const downloadMPR = async () => {
    const { year, monthIndex } = downloadMPRForm.yearMonth;
    downloadMPRForm.processing = true;
    
    try {
        const response = await fetch('/mpr/export-mpr', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content,
                'X-Requested-With': 'XMLHttpRequest' // 让认证中间件识别为AJAX请求
            },
            body: JSON.stringify({ year, month: monthIndex }),
        });
        
        if (!response.ok) throw new Error('下载失败');
        
        const blob = await response.blob();
        const url = window.URL.createObjectURL(blob);
        const a = document.createElement('a');
        a.href = url;
        a.download = 'mpr.xlsx';
        document.body.appendChild(a);
        a.click();
        window.URL.revokeObjectURL(url);
        document.body.removeChild(a);
    } catch (err) {
        console.error(err);
        // 可添加前端错误提示
    } finally {
        downloadMPRForm.processing = false;
    }
}
</script>

关键注意事项

  • 避免用Inertia的post/get方法处理文件下载:Inertia核心是SPA页面交互,不支持直接解析文件下载响应。
  • 认证中间件适配:POST请求需添加X-Requested-With: XMLHttpRequest头,确保$request->expectsJson()返回true,防止被重定向到登录页。

内容的提问来源于stack exchange,提问作者HV Sharma

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 23:53:22