response()->json($data, 201) chooses the status of a JSON body, and response()->noContent() sends
download($path, $name) sends a file as an attachment and file($path) sends it for display.
The streaming methods write output as it is produced:
return response()->eventStream(function (): Generator {
foreach (Product::orderBy('stock')->limit(2)->cursor() as $p) {
yield new StreamedEvent(event: 'stock', data: $p->only('sku', 'stock'));
sleep(1);
}
});$ ts() { while IFS= read -r l; do echo "[$(date -u +%T)] $l"; done; } # arrival time
$ curl -sN $B/export/stock-events | ts
[07:50:17] event: stock
[07:50:17] data: {"sku":"BK-1005","stock":0}
[07:50:17]
[07:50:18] event: stock
[07:50:18] data: {"sku":"BK-1002","stock":3}
[07:50:18]
[07:50:19] event: update
[07:50:19] data: </stream>
[07:50:19]Events arrived a second apart because each yield is flushed; stream() does the same for any generator. The final </stream> event tells EventSource or @laravel/stream-react to close. streamDownload() and streamJson() fed from a cursor() keep memory flat at any size. File responses mark themselves public, so a private header passed to download() needed ->setPrivate(). A stream holds a PHP-FPM worker while open; for mass pushes use Reverb 2,157 (Running Laravel Reverb).