# 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.

- URL: https://laravel-vuejs.space/laravel-csv-export-vue
- Author: Anass Ez-zouaine (https://laravel-vuejs.space/author/anass-ez-zouaine)
- Published: 2026-10-11
- Topics: Laravel, VueJs

People searching “Laravel CSV export Vue” load `Post::all()` and return a string. Stream it. The [pagination guide](https://laravel-vuejs.space/laravel-vue-pagination) 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

**Q: 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.

**Q: 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.
