Download a CSV from a Vue button

streamDownload writes the CSV. The button is an anchor, not an Inertia Link. cursor() keeps the memory flat.

For your AI agent

Copies a prompt. Paste it into the AI agent you already have open.

Read https://laravel-vuejs.space/laravel-csv-export-vue.md
streamDownload writes the CSV. The button is an anchor, not an Inertia Link. cursor() keeps the memory flat.
Do not build the CSV in a computed property from the current page of results.
Show the diff. Do not commit.
On this page · 3 sections
  1. The fix
  2. What to avoid
  3. FAQ

People searching “Laravel CSV export Vue” load Post::all() and return a string. Stream it. The pagination guide is why a list page does not load every row. An export should not either.

TL;DR

  • streamDownload writes the CSV.
  • The button is an anchor, not an Inertia Link.
  • cursor() keeps the memory flat.
  • Do not build the CSV in a computed property from the current page of results.

Who it's for: Laravel + Vue developers

Applies to: Laravel 13 · Vue 3

The fix#

php
public function export(): StreamedResponse
{
    $this->authorize('viewAny', Post::class);

    return response()->streamDownload(function () {
        $out = fopen('php://output', 'w');
        fputcsv($out, ['id', 'title']);

        foreach (Post::query()->orderBy('id')->cursor() as $post) {
            fputcsv($out, [$post->id, $post->title]);
        }

        fclose($out);
    }, 'posts.csv');
}
vue
<a href="/posts/export">Download CSV</a>

A <Link> would try to mount the file as a page. A normal anchor lets the browser download it.

What to avoid#

Gotcha

Do not build the CSV in a computed property from the current page of results. That exports twelve rows and calls it the database. Do not skip authorize. An export is the whole table.

FAQ#

How do I download a CSV from a Vue button?

streamDownload writes the CSV. The button is an anchor, not an Inertia Link. cursor() keeps the memory flat.

What goes wrong with Laravel CSV export Vue?

Many developers load Post::all() and return a string. Do not build the CSV in a computed property from the current page of results.

Found this useful?

Ask questions, share what you built.

Join thousands of Laravel and Vue developers in our Facebook group, or get new posts in your Telegram feed. Sharing this article helps too.

Keep reading

Newsletter

Get the best of Laravel & Vue, once a month.

One short email with new guides, release notes worth reading and hand-picked community links. No spam, unsubscribe any time.