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();
}