關於 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和基本功不扎實吧。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM