【问题标题】:How can I use chunked transfer encoding in Laravel?如何在 Laravel 中使用分块传输编码?
【发布时间】:2019-02-12 01:41:15
【问题描述】:

美好的一天。我想知道我是否可以在 API 响应中使用分块传输编码(进一步的 CTE)?我在数据库中有大量数据,我需要在一个请求中将其传输给客户端。我已经阅读了很多关于 CTE 机制的内容,但很遗憾,我找不到如何实现这一点。

要提到的重要一点:没有分页。它应该是一个自治系统,将数据返回到客户端的端点,而不是返回到网页。

正如我所提到的,数据存储在数据库中。唯一的问题是如何将数据拆分成段(块)并在一个 API 响应中(一个接一个)发送。

谢谢。

【问题讨论】:

  • 我不太明白分块传输编码与问题有什么关系。 “将数据拆分为段”是什么意思?简单地将整个结果集发回,您遇到了什么问题?我们到底在谈论多少条记录?
  • 例如,它可以包含 10 条记录,但每条记录都有一个包含 100k+ 条目的 json 字段。
  • 因此,将每个条目作为一个块逐个流式传输是完美的。

标签: php laravel rest http http-1.1


【解决方案1】:

在我的具体情况下,我通过使用以下代码(示例)解决了我的问题:

use Symfony\Component\HttpFoundation\StreamedResponse;

$response = new StreamedResponse();
$response->setCallback(function () {
    var_dump('Hello World');
    flush();
    sleep(2);
    var_dump('Hello World');
    flush();
});
$response->send();

【讨论】:

    【解决方案2】:

    我想你可能对查询生成器上的 chunk 方法感兴趣。

    分块结果

    如果您需要处理数千条数据库记录,请考虑使用 块方法。此方法检索一小部分结果 一次并将每个块馈送到闭包中进行处理。这 方法对于编写处理的 Artisan 命令非常有用 数千条记录。例如,让我们与整个用户一起工作 一次包含 100 条记录的表:

    $response = new \Symfony\Component\HttpFoundation\StreamedResponse(function() {
        $handle = fopen('php://output', 'w');
    
        DB::table('users')->orderBy('id')->chunk(100, function ($users) use($handle) {
            foreach ($users as $user) {
                fputs($handle, json_encode($user));
            }
        });
    
        fclose($handle);
    });
    
    return $response;
    

    延伸阅读:https://laravel.com/docs/master/queries#chunking-results

    分块传输编码

    据我所知,如果您返回 JSON 响应,Laravel does this by default

    更新:

    我的解决方案过于复杂和复杂。我已经删除了StreamedResponse,因为真的不需要它。请参阅下面的更新示例。

    $json_response = collect();
    
    DB::table('users')->orderBy('id')->chunk(100, function ($users) use($json_response) {
        foreach ($users as $user) {
            $json_response->push($user);
        }
    });
    
    return $json_response->toJson();
    

    【讨论】:

    • 关于第一段:你误会我了。我的意思是分块发送数据,而不是 GET。
    • 关于第二段:数据还是照常传输,没有分块。所以我请你帮我创建一个函数来将 Eloquent 模型转换为分块结果。
    • 如果您想发送数据,那么我会亲自为用户设置一个端点,您可以在其中使用查询构建器上的块方法 - 无论您是在 eloquent 模型上设置还是在控制器是您的选择 - 您将能够chunk 将其降低到可由客户管理。我真的相信您正在寻找的是我在回答中展示的方法。为了更好地理解你的困境,也许你可以告诉我——如果是这样的话——为什么你不能使用上述方法。
    • 我无法理解第一种方法的重点。循环虽然为了做什么?没什么...该方法仅用于分块 Eloquent 模型,而不是 API 响应。 CTE 机制执行以下操作(据我所知):它将数据转换为字节码,但之前它将每个字符串转换为换行符、数据长度和实际数据的组合。听起来很复杂(维基百科解释得更好)。但是上面的方法只是对数据库记录进行分块。
    • @Nod 我添加了一个新示例,希望对您有所帮助。您可能需要自定义标头以指示它是 JSON 响应,但除此之外应该没问题。 :)
    猜你喜欢
    • 2014-07-01
    • 2023-03-16
    • 2017-07-22
    • 1970-01-01
    • 1970-01-01
    • 2011-01-17
    • 1970-01-01
    • 2017-11-19
    • 2018-04-04
    相关资源
    最近更新 更多