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

Laravel-excel导出文件无法下载仅存缓存目录问题求助

问题:Laravel Excel导出文件仅保存到缓存目录,不触发浏览器下载

在Laravel项目中使用laravel-excel包导出数据库数据,已能获取正确数据,但文件不会触发浏览器下载,仅保存到storage\framework\cache\laravel-excel目录。

前端Vue代码

<script setup>
import { router} from '@inertiajs/vue3';
import { ref } from 'vue'
const props = defineProps({transactions:Object});

const status =ref('Status');
const shop =ref('Shop');

const handleExport = ()=>{
    const formData = new FormData();
    formData.append('status', status.value);
    formData.append('shop', shop.value);
   
    router.post('/export_data', formData,{
         preserveState: true, preserveScroll: true,
    })
}
</script>

<template>
    <button @click="handleExport()" type="button"></button>
</template>

后端控制器代码

<?php

namespace App\Http\Controllers;

use App\Exports\TransactionsExport;
use App\Models\Transaction;
use Illuminate\Http\Request;
use Maatwebsite\Excel\Facades\Excel;

class TransactionController extends Controller
{
    public function export_data(Request $request)
    {
        $status =  $request['status'];
        $shop = $request['shop'];
        
        $result =  Transaction::where([['status',$status],['shop',$shop]])->get();
        return Excel::download(new TransactionsExport($result), 'Transactions.xlsx');
    }
}

解决方案

原因

Inertia.js的router.post默认处理JSON/HTML类型的响应,无法自动识别并触发Excel这类二进制流的下载操作,导致文件仅被后端缓存而不推送给浏览器。

1. 修改前端代码,用原生Fetch处理下载请求

替换原有的handleExport方法,直接通过Fetch获取二进制响应,手动触发浏览器下载:

<script setup>
import { ref } from 'vue'
const props = defineProps({transactions:Object});

const status = ref('Status');
const shop = ref('Shop');

const handleExport = async () => {
    const formData = new FormData();
    formData.append('status', status.value);
    formData.append('shop', shop.value);

    try {
        const response = await fetch('/export_data', {
            method: 'POST',
            headers: {
                'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content
            },
            body: formData
        });

        if (!response.ok) throw new Error('导出请求失败');

        // 处理二进制响应,触发下载
        const blob = await response.blob();
        const downloadUrl = window.URL.createObjectURL(blob);
        const link = document.createElement('a');
        link.href = downloadUrl;
        link.download = 'Transactions.xlsx';
        document.body.appendChild(link);
        link.click();
        
        // 清理临时资源
        window.URL.revokeObjectURL(downloadUrl);
        document.body.removeChild(link);
    } catch (error) {
        console.error('导出失败:', error);
    }
}
</script>

<template>
    <button @click="handleExport()" type="button">导出数据</button>
</template>

2. 优化后端控制器(可选)

明确指定响应头,确保Laravel正确输出Excel文件的MIME类型:

<?php

namespace App\Http\Controllers;

use App\Exports\TransactionsExport;
use App\Models\Transaction;
use Illuminate\Http\Request;
use Maatwebsite\Excel\Facades\Excel;

class TransactionController extends Controller
{
    public function export_data(Request $request)
    {
        $status = $request->input('status');
        $shop = $request->input('shop');
        
        $result = Transaction::where('status', $status)
                            ->where('shop', $shop)
                            ->get();
                            
        return Excel::download(new TransactionsExport($result), 'Transactions.xlsx')
                    ->header('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
    }
}

关键说明

  • Inertia路由仅适用于页面组件交互,不适合处理文件下载这类二进制响应场景。
  • 必须携带CSRF令牌,否则Laravel会拦截POST请求。
  • 前端通过创建临时链接触发下载是处理二进制文件的标准方式,完成后需清理临时资源避免内存泄漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 14:38:16