关于 MemoryStream 的多次写入,模拟post请求,接收方 .net core web api无法读取到流数据,报 System.IO.IOException: Unexpected end of Stream, the content may have already be en read by another component.
主要是业务不熟害死人。记录一下。真想抽自己几个嘴巴子
先说结论,知道这个结论的下面文字都是废话:
一、new MemoryStream 的时候,如果需要分次写入,只能是像下面这样子
MemoryStream ms =new MemoryStream()
ms.write(第一次的byte[])
ms.write(第二次的byte[])
而不能像下面这样子。
MemoryStream ms =new MemoryStream(第一次的byte[])
ms.writer(第二次的byte[])
如果像下面这样子,ms的大小是固定的,写入的时候会把之前写入的覆盖
二、如果是把ms赋值给其他字段,需要把 ms 的Position设置为0,即 ms.Position=0,否则别人可能读不到数据。
再说一下自己艰辛的调试过程
在捣鼓ocelot网关中心,转发一个请求去别人的服务器,这个请求是 Content-Type: multipart/form-data;
既有参数,又有文件。
但是我网关收到参数后,需要对参数进行一定的鉴权,再转发参数去别人的下游服务。
所以我就把参数全部取出来后做处理了,处理完了以后,需要把它弄成一个Stream流 放在Body中。这个是一个.net core 的中间件
当我很开心的处理完了以后,以为没什么问题,postman搞起,结果并没有得到自己想要的结果,似乎对方的服务器没收到参数。
我的body体大概就是像下面这个,(先忽略文件,不好表述,用文本的好表述)
----------------------------585497138534118524577705
Content-Disposition: form-data; name="userId"
123
----------------------------585497138534118524577705
Content-Disposition: form-data; name="username"
1111111
----------------------------585497138534118524577705--
然后我发现,假设我先把这整段body体拼好设定变量 string bodyStr=上面那段body,然后 MemoryStream ms=new MemoryStream (Encoding.GetEncoding(charset).GetBytes(bodyStr);
然后 httpContext.Request.Body = ms; 这样子请求,对方正常接到参数。
假设我分次 ms.write() ,对方怎么都收不到参数。
我分词伪代码大概就是
MemoryStream ms =new MemoryStream(第一次的byte[])
ms.writer(第二次的byte[])
我又不能问对方(对方是淘宝。。。没空帮我查这种自己写代码造成的问题)
然后我就把 ms 又转回字符串去观察,发现第一次写入的bytep[]的字符串总会少一些,果断去查资料。
原来实例化 MemoryStream 的时候,如果传入了 byte[] ,那这个内存块就是固定大小的,所以会一直覆盖吧。
所以我代码换成了
MemoryStream ms =new MemoryStream()
ms.write(第一次的byte[])
ms.write(第二次的byte[])
心里想着这次应该对了。结果对方似乎还是收不到我的参数。我特么。。。。
我继续把ms的字符串打印出来观察,发现的的确确已经对了,类似下面这个
----------------------------585497138534118524577705
Content-Disposition: form-data; name="userId"
123
----------------------------585497138534118524577705
Content-Disposition: form-data; name="username"
1111111
----------------------------585497138534118524577705--
所以,我写给对方的body体肯定对了,对方也不可能出错,毕竟对方是淘宝。
这里面肯定还有问题。没办法,既然找不到他们答复,那我就只能把请求转发给我自己的下游先试试了
我马上拿web api 搭建了一个 printPara()的方法。主要代码是 打印当前请求的所有参数以及请求头键值对。
结果发现,.net core 给我报了一个错 ,如下图
所以,没跑了,对方肯定也是这样子了。
然后,百度各种搜这个错误,好像没什么有价值的资料。
但是我估摸着,它既然提示说这个流可能被其他人读过了,那答案应该就只有一个,大概就是指针位置到末尾了。所以我就尝试在第二次 ms.write 后把 ms.Position=0 给加上。
再发请求,就可以了。。。
唉。主要还是业务部署害死自己。整整调了一个下午加晚饭后的休息时间。唉
主要还是因为极少用这个MemoryStream和基本功不扎实吧。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构