Метод stream
Метод stream класса Response применяется для создания
потокового ответа, который передаётся клиенту частями.
Это особенно полезно при работе с большими файлами,
генерации данных в реальном времени или при необходимости
экономии памяти сервера. Метод принимает два основных
параметра: первый - это callable-функция, которая будет
выводить данные, второй - необязательный массив заголовков.
Синтаксис
<?php
use Illuminate\Support\Facades\Response;
Response::stream($callback, $status, $headers);
?>
Пример
Давайте передадим большой текстовый файл по частям:
<?php
use Illuminate\Support\Facades\Response;
Route::get('/stream-text', function () {
$filePath = storage_path('app/large-file.txt');
return Response::stream(function () use ($filePath) {
$handle = fopen($filePath, 'r');
while (!feof($handle)) {
echo fread($handle, 1024);
ob_flush();
flush();
}
fclose($handle);
}, 200, [
'Content-Type' => 'text/plain',
'Content-Disposition' => 'attachment; filename="large-file.txt"'
]);
});
?>
Результат выполнения кода:
"part1 part2 part3 ..."
Пример
Давайте сгенерируем и передадим данные в формате CSV:
<?php
namespace App\Http\Controllers;
use Illuminate\Support\Facades\Response;
use App\Models\User;
class ReportController extends Controller
{
public function export()
{
return Response::stream(function () {
$handle = fopen('php://output', 'w');
fputcsv($handle, ['ID', 'Name', 'Email']);
User::chunk(100, function ($users) use ($handle) {
foreach ($users as $user) {
fputcsv($handle, [
$user->id,
$user->name,
$user->email
]);
}
});
fclose($handle);
}, 200, [
'Content-Type' => 'text/csv',
'Content-Disposition' => 'attachment; filename="users.csv"'
]);
}
}
?>
Пример
Давайте реализуем передачу данных в реальном времени (Server-Sent Events):
<?php
use Illuminate\Support\Facades\Response;
Route::get('/stream-events', function () {
return Response::stream(function () {
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
for ($i = 1; $i <= 10; $i++) {
echo "data: Event " . $i . "\n\n";
ob_flush();
flush();
sleep(1);
}
}, 200, [
'Content-Type' => 'text/event-stream',
'Cache-Control' => 'no-cache'
]);
});
?>