Using an ASP.NET Core 6 Web API written in C# with minimal API, I would like to return a stream of data without first loading the data into memory. In my case this is JSONL (JSON lines) data that is written by Apache Spark. JSONL is a text-based format.
This code below sets the Content-Type: application/json
which is not correct for my use case. Setting this type then wraps the entire content with an array and adds escape backslash characters all through where there are quotes.
It should instead set Content-type: text/plain
which would preserve the original formatting of the lines, and allow the consumers of this endpoint to stream and process one line at a time without loading the entire response body into memory on the client.
Is it possible to change this content-type
while keeping the stream Transfer-Encoding: chunked
and with it not parsing or modifying the line content I am reading from the .jsonl file?
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();
});
You can set up a custom IResult
that handles the line per line reading and writing to the response.
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);
}
}
}
}
Your MapGet
will look like below.
app.MapGet("/stream/data", () => new JsonLines(@"c:\yourdatafile.json"));
Fiddler shows that the expected headers are present, and that the response is chunked.
You might reconsider setting the Content-Type
header (back) to application/json
since ASP.NET Core will not touch upon the content anymore.