【问题标题】:Proper way to read and write web api response stream读写web api响应流的正确方法
【发布时间】:2023-03-13 23:29:01
【问题描述】:

我在找到正确的咒语时遇到了一些麻烦,该咒语允许我写入响应流,然后在测试中读取内容。目前我有这个

var res = new HttpResponseMessage(System.Net.HttpStatusCode.OK);
var ms = new MemoryStream();
res.Content = new StreamContent(ms);
using (var sw = new StreamWriter(ms, System.Text.Encoding.UTF8))
using (var csv = new CsvHelper.CsvWriter(sw))
  csv.WriteRecords(allData.ToList());
return res;

在我的测试中,我正在尝试阅读此响应

  var controller = appContainer().Resolve<MyController>();
  var res = (await controller.Get()) as HttpResponseMessage;
  res.ShouldNotEqual(null);
  var csv = await res.Content.ReadAsStringAsync();

最后一行产生错误

Error while copying content to a stream.
  ----> System.ObjectDisposedException : Cannot access a closed Stream.

所以这里有几件事

  • 为什么会发生此错误,如何在测试中正确防止它发生?
  • MemoryStream 的使用不适合我,我不应该能够直接写入内容流吗? MemoryStream 是不是可能会极大地增加我的内存使用量?

【问题讨论】:

  • using 语句导致流被释放。
  • 没有不加倍内存使用。内容的流是您分配给它的流。检查源代码
  • @Nkosi 所以假设我正在写 10MB 的 CSV。我需要 10MB 的内存块来缓冲这些。但是坚持住!我可以在不将整个 csv 渲染到内存的情况下开始发回身体的某些部分,因此我不会实际上一次需要整个 10MB,而是需要一个更小的移动窗口。这就是你对FileStreamResult 所做的事情,我想在这里获得类似的效率。
  • @GeorgeMauer 你有没有找到解决方案?您在 question 中制作了类似的 cmets,但没有发布解决方案。
  • @Nse 刚刚检查了我最终做了什么,实际上我确实使用了内存流。我不太确定这是一个 asp.net web api 问题,但是 - 这可能是一个 CsvHelper 错误,因为处理 CsvWriter 会关闭底层流。未来的版本可以选择不这样做,但我已经查看了代码和我正在使用的版本(2.16.3.0),实际上可以保留未处理、刷新流写入器并重置内存流位置

标签: c# asp.net-web-api stream


【解决方案1】:

只是把它放在那里,虽然它并不完美......使用 PushStreamContent 做了很多工作,但它也有它自己的麻烦 - 即你的匿名方法可能产生的任何异常都会被吞没并且难以跟踪没有完全重现问题。当炸弹爆炸时,Web api 未处理的异常处理程序将生效的管道点顺利通过,并且 xmlhttprequest 似乎无法识别闭包。

例如像

HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
response.Content = new PushStreamContent((stream, content, context) =>
{
     // write your output here
});
return response;

只要内部方法永远不会出错或以任何方式出错,就会得到你想要的。

PushStreamContent 会在调用匿名方法之前立即刷新您的 http 标头,因此您会被分块,以后无法将其卷回。

您可以在匿名方法中添加一个 try/catch,以便在出现问题时给自己留言,但根据我的经验,XmlHttpRequest 无法识别远程服务器何时强制关闭请求,因此它会继续等待。当我把 Fiddler 放在那里时,我才开始弄清楚发生了什么,Fiddler 尖叫起来。

【讨论】:

    猜你喜欢
    • 2015-09-21
    • 1970-01-01
    • 2019-09-27
    • 2016-09-12
    • 1970-01-01
    • 2017-03-07
    • 1970-01-01
    • 1970-01-01
    • 2018-07-02
    相关资源
    最近更新 更多