簡體   English   中英

Web Api 請求拋出“將內容復制到流時出錯”。

[英]Web Api Request Throws "Error while copying content to a stream."

我正在嘗試實現此代碼示例,但收到HttpRequestException -“將內容復制到流時出錯”。 ReadAsStringAsync()方法被調用時。 內部異常是“無法訪問已處理的對象” 我正在使用 Fiddler 提出請求。 我不明白。 有人可以解釋為什么我會收到此異常並提供解決方案嗎?

Web API 方法:

public async Task<HttpResponseMessage> Post(HttpRequestMessage request)
{
    try
    {
        var jsonString = await request.Content.ReadAsStringAsync();
    }
    catch (Exception ex)
    {                
        throw;
    }
    return new HttpResponseMessage(HttpStatusCode.Created);
}

提琴手(POST):

User-Agent: Fiddler
Host: localhost:23567
Content-Length: 18
Content-Type: application/json; charset=utf-8
Body{"Test":1}

編輯:

我有線索,但需要驗證。 在 Web Api 控制器上,我有一個ActionFilterAttribute ,在它的OnActionExecuting覆蓋中,有這一行:

public override async void OnActionExecuting(HttpActionContext actionContext)
{
    // omitted code
    actionContext.Request.Content.ReadAsStreamAsync();
}

會不會是因為內容是在這里閱讀的,所以不能再使用了? 如果是這樣,我如何使其在方法中可用? 這里的Content和HttpRequestMessage一樣嗎? 可能包含一個答案。

只是一個猜測,應該作為評論發布,但我想包含一個代碼片段:

也許您在using塊中調用Post函數,但不要使用await

using (HttpRequestMessage request = ...)
{
    // Maybe you use this:
    Post(request);

    // Instead of this
    var response = await Post(request);
}

或者你沒有正確處理舊的連接。

另外,嘗試將HttpVersion.Version10添加到您的請求中,它將標頭請求從Connection: keep-alive更改為Connection: close ,這可能會導致在某些情況下您重用主機的異常(搜索更多信息)

request.Version = HttpVersion.Version10;
var jsonString = await request.Content.ReadAsStringAsync();

由於控制器的ActionFilterAttribute's OnActionExecuting方法正在調用ReadAsStreamAsync ,因此無法再次讀取內容。 我將ReadAsStreamAsync更改為ReadAsStringAsync並且請求的內容在控制器中可用。 顯然, ReadAsStringAsync 緩沖內容,因此它仍然可用。 鏈接提供了答案。

我希望這個(遲到的)帖子有一天會幫助某人......

簡而言之:接受的答案建議將整個文件作為字符串(而不是流)讀取以繞過讀取問題

但是......將文件作為字符串讀取並不是一個好主意

我想通了,與MultipartMemoryStreamProvider更換MultipartFormDataStreamProvider的偉大工程-讓你讀你上傳的文件根據需要

我的代碼(至少是它的相關部分)

    [HttpPost]
    [Route("upload/file")] // you may replace this route to suit your api service
    public async Task<IHttpActionResult> Upload()
    {
        if (!Request.Content.IsMimeMultipartContent("form-data"))
        {
            return BadRequest("Unsupported media type");
        }

        try
        {
            var provider = new MultipartMemoryStreamProvider();

            await Request.Content.ReadAsMultipartAsync(provider);

            if (provider.Contents.Count == 0) return InternalServerError(new Exception("Upload failed"));

            var file = provider.Contents[0]; // if you handle more then 1 file you can loop provider.Contents

            var buffer = await file.ReadAsByteArrayAsync();

            // .. do whatever needed here

            return Ok();

        }
        catch (Exception ex)
        {
            return BadRequest(ex.GetBaseException().Message);
        }
    }

我解決了這個問題,我的問題是響應在 gzip 中:

var handler = new HttpClientHandler();
        if (handler.SupportsAutomaticDecompression)
        {
            handler.AutomaticDecompression = DecompressionMethods.GZip |
                                             DecompressionMethods.Deflate;
        }
        client = new HttpClient(handler);

var content = new FormUrlEncodedContent(valoresPost);
var response = await client.PostAsync(url, content);
        
                var contenidoPdf = await response.Content.ReadAsByteArrayAsync();
             

我正在添加到對話中,因為我在不同的上下文中遇到了這個錯誤。 對我來說,我有一個從我的網絡應用程序到一個單獨的 API 的現有調用。 它以前可以正常工作然后停止,我收到此錯誤並且無法找到原因。 結果是我的實體框架中的循環引用,本質上是兩個不應該存在的對象之間的導航屬性。 它並沒有破壞 API,因為我認為 EF 具有導航屬性將填充的深度的默認配置,以防止堆棧溢出,但它肯定已經使接收端的流不堪重負並導致連接超時。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM