Класс StreamedResponse
Класс StreamedResponse применяется для отправки данных клиенту в виде потока.
Это особенно полезно при работе с большими объёмами данных, когда нет необходимости
загружать весь результат в память перед отправкой. Потоковый ответ принимает
в конструкторе коллбек-функцию, которая выполняет фактическую отправку данных,
а также код состояния HTTP и массив заголовков.
Синтаксис
<?php
use Illuminate\Http\StreamedResponse;
$response = new StreamedResponse(
$callback,
$status = 200,
$headers = []
);
?>
Первый параметр $callback - это функция, которая будет выполняться при отправке ответа.
Второй параметр $status определяет код состояния HTTP (по умолчанию 200).
Третий параметр $headers позволяет передать дополнительные заголовки ответа.
Пример
Давайте создадим простой потоковый ответ, который отправляет данные с задержкой:
<?php
use Illuminate\Support\Facades\Route;
use Illuminate\Http\StreamedResponse;
Route::get('/stream', function () {
return new StreamedResponse(function () {
$res = ['a', 'b', 'c', 'd', 'e'];
foreach ($res as $value) {
echo $value . "\n";
ob_flush();
flush();
usleep(500000);
}
}, 200, [
'Content-Type' => 'text/plain',
'Cache-Control' => 'no-cache',
]);
});
?>
Результат выполнения кода при обращении к маршруту '/stream':
a
b
c
d
e
Каждая буква выводится с интервалом в 0.5 секунды, демонстрируя потоковую передачу данных.
Пример
Давайте создадим потоковый ответ для передачи данных CSV с использованием генератора:
<?php
use Illuminate\Support\Facades\Route;
use Illuminate\Http\StreamedResponse;
Route::get('/export/csv', function () {
$res = [
['id' => 1, 'name' => 'user1', 'email' => 'user1@example.com'],
['id' => 2, 'name' => 'user2', 'email' => 'user2@example.com'],
['id' => 3, 'name' => 'user3', 'email' => 'user3@example.com'],
];
return new StreamedResponse(function () use ($res) {
$handle = fopen('php://output', 'w');
fputcsv($handle, ['ID', 'Name', 'Email']);
foreach ($res as $row) {
fputcsv($handle, $row);
}
fclose($handle);
}, 200, [
'Content-Type' => 'text/csv',
'Content-Disposition' => 'attachment; filename="export.csv"',
]);
});
?>
Результат выполнения кода при обращении к маршруту '/export/csv':
ID,Name,Email
1,user1,user1@example.com
2,user2,user2@example.com
3,user3,user3@example.com
Потоковый ответ формирует CSV-файл и отправляет его клиенту как вложение для скачивания.
Пример
Давайте создадим потоковый ответ для отправки больших данных из базы данных
с использованием метода chunk для оптимизации памяти:
<?php
use Illuminate\Support\Facades\Route;
use Illuminate\Http\StreamedResponse;
use App\Models\Article;
Route::get('/articles/export', function () {
return new StreamedResponse(function () {
$res = Article::chunk(100, function ($chunk) {
foreach ($chunk as $article) {
echo $article->id . ',' . $article->title . ',' . $article->created_at . "\n";
}
});
}, 200, [
'Content-Type' => 'text/plain',
'Content-Disposition' => 'attachment; filename="articles.txt"',
]);
});
?>
Результат выполнения кода при обращении к маршруту '/articles/export':
"1,article 1,2024-01-01 12:00:00"
"2,article 2,2024-01-02 12:00:00"
"3,article 3,2024-01-03 12:00:00"
Данные из базы обрабатываются порциями по 100 записей, что позволяет экономить память при экспорте больших объёмов данных.
Смотрите также
-
класс
Response,
который является базовым классом для всех HTTP-ответов -
метод
stream,
который создаёт потоковый ответ из вспомогательной функции -
класс
BinaryFileResponse,
который используется для отправки файлов из файловой системы -
метод
file,
который отправляет файл непосредственно из хранилища