本文目录导读:

- 基本流式响应
- 使用 Laravel 封装的
response()->stream() - 大文件下载示例
- 实时数据流(SSE - Server Sent Events)
- 数据库大量数据导出
- 后端代码配合前端接收
- 注意事项
在 Laravel 中,流式响应(Streamed Response)主要用于处理大文件下载或实时数据推送,避免一次性加载大量数据到内存中,以下是具体用法:
基本流式响应
use Symfony\Component\HttpFoundation\StreamedResponse;
Route::get('/stream', function () {
return new StreamedResponse(function () {
// 逐行输出数据
for ($i = 1; $i <= 100; $i++) {
echo "Line $i\n";
flush(); // 立即发送数据到客户端
usleep(100000); // 模拟延迟
}
}, 200, [
'Content-Type' => 'text/plain',
]);
});
使用 Laravel 封装的 response()->stream()
Route::get('/stream', function () {
return response()->stream(function () {
// 生成大文件内容
$data = ['item1', 'item2', 'item3'];
foreach ($data as $item) {
echo json_encode($item) . "\n";
ob_flush();
flush();
}
}, 200, [
'Content-Type' => 'application/json'
]);
});
大文件下载示例
Route::get('/large-file', function () {
$filePath = storage_path('app/large-file.txt');
return response()->stream(function () use ($filePath) {
$handle = fopen($filePath, 'r');
if ($handle) {
while (!feof($handle)) {
echo fgets($handle);
ob_flush();
flush();
}
fclose($handle);
}
}, 200, [
'Content-Type' => 'text/plain',
'Content-Disposition' => 'attachment; filename="download.txt"'
]);
});
实时数据流(SSE - Server Sent Events)
Route::get('/sse', function () {
return response()->stream(function () {
set_time_limit(0); // 取消脚本执行时间限制
for ($i = 0; $i < 10; $i++) {
$data = [
'time' => now()->toDateTimeString(),
'value' => rand(1, 100)
];
echo "data: " . json_encode($data) . "\n\n";
ob_flush();
flush();
sleep(2); // 每2秒发送一次数据
}
// 发送结束信号
echo "event: end\ndata: stream finished\n\n";
ob_flush();
flush();
}, 200, [
'Content-Type' => 'text/event-stream',
'Cache-Control' => 'no-cache',
'Connection' => 'keep-alive',
'X-Accel-Buffering' => 'no', // 禁用 Nginx 缓冲
]);
});
数据库大量数据导出
use App\Models\User;
Route::get('/export-users', function () {
return response()->stream(function () {
// 设置响应头
echo "ID,Name,Email\n";
// 使用游标批量处理
User::cursor()->each(function ($user) {
echo "{$user->id},{$user->name},{$user->email}\n";
ob_flush();
flush();
});
}, 200, [
'Content-Type' => 'text/csv',
'Content-Disposition' => 'attachment; filename="users.csv"'
]);
});
后端代码配合前端接收
前端 JavaScript 示例:
// 使用 fetch API 接收流式响应
async function fetchStream() {
const response = await fetch('/stream');
const reader = response.body.getReader();
const decoder = new TextDecoder();
while (true) {
const { done, value } = await reader.read();
if (done) break;
const chunk = decoder.decode(value);
console.log('Received:', chunk);
// 更新 UI 元素
document.getElementById('output').textContent += chunk;
}
}
// 或者使用 EventSource 接收 SSE
const eventSource = new EventSource('/sse');
eventSource.onmessage = function(event) {
console.log('Received:', event.data);
document.getElementById('output').textContent += event.data + '\n';
};
eventSource.addEventListener('end', function() {
console.log('Stream finished');
eventSource.close();
});
注意事项
-
缓存问题:如果使用 Nginx,需要禁用缓冲区:
proxy_buffering off; -
PHP 配置:确保设置合适的
max_execution_time -
输出缓冲:使用
ob_flush()和flush()确保数据及时发送 -
浏览器兼容性:部分浏览器可能需要特定的响应头
-
内存管理:流式响应的主要优势就是内存友好,避免加载大量数据
流式响应非常适合处理大文件下载、实时数据更新、日志流等场景。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播