如何使用最少的 API 从 Web API 返回分块文本/纯内容

问题描述 投票:0回答:2

使用用 C# 编写的 ASP.NET Core 6 Web API 和最少的 API,我想返回数据流,而无需先将数据加载到内存中。就我而言,这是由 Apache Spark 编写的 JSONL(JSON 行)数据。 JSONL 是一种基于文本的格式。

下面的代码设置了

Content-Type: application/json
,这对于我的用例来说是不正确的。设置此类型然后用数组包装整个内容,并在所有引号的地方添加转义反斜杠字符。

它应该设置

Content-type: text/plain
,这将保留行的原始格式,并允许该端点的使用者一次流式传输和处理一行,而无需将整个响应正文加载到客户端的内存中。

是否可以在保留流

content-type
的同时更改此
Transfer-Encoding: chunked
,并且不解析或修改我从 .jsonl 文件中读取的行内容?

app.MapGet("/stream/data", () =>
{
    async IAsyncEnumerable<string> Stream()
    {
        using (StreamReader file = new StreamReader(filePath))
        {
            while (!file.EndOfStream)
            {
                yield return await file.ReadLineAsync() ?? string.Empty;
            }
        }
    }

    return Stream();
});
c# stream asp.net-core-webapi minimal-apis jsonlines
2个回答
6
投票

您可以设置一个自定义

IResult
来处理每行读取和写入响应。

public sealed class JsonLines : IResult
{
    private readonly string _filePath;

    public JsonLines(string filePath)
        => _filePath = filePath;

    public async Task ExecuteAsync(HttpContext httpContext)
    {
        httpContext.Response.ContentType = "text/plain"; // Or "application/json"

        using var reader = new StreamReader(_filePath);

        while (!reader.EndOfStream)
        {
            var line = await reader.ReadLineAsync();
            if (line is not null)
            {
                await httpContext.Response.WriteAsync(line);
            }
        }
    }
}

您的

MapGet
将如下所示。

app.MapGet("/stream/data", () => new JsonLines(@"c:\yourdatafile.json"));

Fiddler 显示存在预期的标头,并且响应已分块。

enter image description here


您可能会重新考虑将

Content-Type
标头(背面)设置为
application/json
,因为 ASP.NET Core 将不再触及内容。


0
投票

我在寻找类似的东西(但更简单)时遇到了这个问题:How to return plain text from a minimary WebApi in general? 我正在使用 .NET 8,发现我可以使用 Results.Text() 方法,如下所示:

app.MapGet("/HelloWorld", () =>
{
    return Results.Text("Hello World!\nYou are looking good today.", "text/plain", Encoding.UTF8, 200);

});
© www.soinside.com 2019 - 2024. All rights reserved.