Skip to content
全部文档

文件下载

Livewire 中的文件下载与 Laravel 本身基本相同。通常,你可以在 Livewire 组件里使用任何 Laravel 下载工具,效果与预期一致。

不过在底层,文件下载的处理方式与标准 Laravel 应用不同。使用 Livewire 时,文件内容会先 Base64 编码,发到前端,再解码回二进制,由客户端直接触发下载。

基本用法

在 Livewire 中触发文件下载很简单:返回标准的 Laravel 下载响应即可。

下面是一个 show-invoice 组件示例,其中有一个「Download」按钮用于下载发票 PDF:

php
<?php // resources/views/components/⚡show-invoice.blade.php

use Livewire\Component;
use App\Models\Invoice;

new class extends Component {
    public Invoice $invoice;

    public function mount(Invoice $invoice)
    {
        $this->invoice = $invoice;
    }

    public function download()
    {
        return response()->download( // [tl! highlight:2]
            $this->invoice->file_path, 'invoice.pdf'
        );
    }
};
blade
<div>
    <h1>{{ $invoice->title }}</h1>

    <span>{{ $invoice->date }}</span>
    <span>{{ $invoice->amount }}</span>

    <button type="button" wire:click="download">Download</button> <!-- [tl! highlight] -->
</div>

和 Laravel 控制器一样,你也可以用 Storage facade 发起下载:

php
public function download()
{
    return Storage::disk('invoices')->download('invoice.csv');
}

流式下载

Livewire 也可以做流式下载;不过并非真正意义上的流式传输。要等文件内容收集完毕并送到浏览器后,才会触发下载:

php
public function download()
{
    return response()->streamDownload(function () {
        echo '...'; // Echo download contents directly...
    }, 'invoice.pdf');
}

测试文件下载

Livewire 还提供了 ->assertFileDownloaded() 方法,便于测试是否已按给定名称下载了文件:

php
use App\Models\Invoice;

public function test_can_download_invoice()
{
    $invoice = Invoice::factory();

    Livewire::test(ShowInvoice::class)
        ->call('download')
        ->assertFileDownloaded('invoice.pdf');
}

也可以用 ->assertNoFileDownloaded() 断言没有下载文件:

php
use App\Models\Invoice;

public function test_does_not_download_invoice_if_unauthorised()
{
    $invoice = Invoice::factory();

    Livewire::test(ShowInvoice::class)
        ->call('download')
        ->assertNoFileDownloaded();
}