【发布时间】:2017-06-02 17:35:00
【问题描述】:
我需要流式传输一个大对象。我无法弄清楚如何分块发送。发布的代码有效,但是,stream.Flush() 只被调用一次。所以,基本上我正在缓冲对象 - 不好。如何多次调用 stream.Flush()?如果我有一个集合,我可以循环流式传输/刷新。那么我该如何处理大对象呢?
服务器代码:
public async Task<HttpResponseMessage> ConvertToTiffAsync([FromBody] DocumentDto dto)
{
// THIS IS LARGE
var document = await _service.ConvertToTiffAsync(dto);
var response = Request.CreateResponse();
response.Content = new PushStreamContent((stream, content, context) =>
{
var serializer = new JsonSerializer();
using (var writer = new StreamWriter(stream))
{
using (var jsonTextWriter = new JsonTextWriter(writer))
{
serializer.Serialize(jsonTextWriter, document);
stream.Flush(); // ONLY CALLED ONCE - NEED MANY CALLS
}
}
});
return response;
}
客户代码(此处未进行流式传输,但需要):
using (var client = new HttpClient(new HttpClientHandler() { UseDefaultCredentials = true }))
{
client.Timeout = new TimeSpan(0, 5, 0);
var stringContent = new StringContent(JsonConvert.SerializeObject(dto), Encoding.UTF8, "application/json");
using (var httpRequest = new HttpRequestMessage(HttpMethod.Post, endpoint))
{
httpRequest.Content = stringContent;
using (HttpResponseMessage response = await client.SendAsync(httpRequest, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false))
{
response.EnsureSuccessStatusCode();
using (var streamReader = new StreamReader(await response.Content.ReadAsStreamAsync()))
using (var jsonReader = new JsonTextReader(streamReader))
{
var serializer = new JsonSerializer();
return await Task.Run(() => serializer.Deserialize<ConvertDocumentDto>(jsonReader)).ConfigureAwait(false);
}
}
}
}
【问题讨论】:
-
你不需要冲洗。 PushStreamContent 所做的基本上是所有写入它的数据都直接流式传输到客户端而不缓冲内容。那么你确定完整的 JSON 表示在内存中吗?
-
另外根据thomaslevesque.com/2013/11/30/…,如果你想流式传输 JSON,你可以使用 new ObjectContent(document, new JsonMediaTypeFormatter()) 而不是 PushStreamContent,它应该做同样的事情,但更简洁。
-
@ckuri ...那篇文章的重点是上传而不是下载。此外,在调用 flush() 之前,我不相信数据是流式传输的——至少我在运行代码时是这样看的。
-
上传和下载的工作方式与在两种情况下都使用 HttpContent 的子类相同。
-
flush 无论如何都无关紧要,因为当您离开 using 块时调用的 StreamWriters Dispose 方法总是调用流 flush 方法。所以这条线是多余的。你到底看到了什么?
标签: c# json stream streaming pushstreamcontent