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.
The fix#
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');
}<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.



