Mor*_*lan 3 c# stream jsonlines asp.net-core-webapi minimal-apis
使用用 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();
});
Run Code Online (Sandbox Code Playgroud)
您可以设置一个自定义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);
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
你的MapGet意志如下所示。
app.MapGet("/stream/data", () => new JsonLines(@"c:\yourdatafile.json"));
Run Code Online (Sandbox Code Playgroud)
Fiddler 显示存在预期的标头,并且响应已分块。
您可能会重新考虑将Content-Type标头(返回)设置为,application/json因为 ASP.NET Core 将不再触及内容。