【问题标题】:HttpWebRequest stream write never completesHttpWebRequest 流写入永远不会完成
【发布时间】:2011-06-02 21:14:31
【问题描述】:

我正在发布一个带有HttpWebRequest 的文件,以及一个页眉和页脚。标题(约 0.5K)和实际文件似乎写得很好,但对于大文件(约 15MB),页脚(大约 29 个字节)似乎永远不会写。

using (Stream requestStream = request.GetRequestStream()) {
    requestStream.Write(postHeaderBytes, 0, postHeaderBytes.Length);

    byte[] buffer = new byte[Math.Min(4096L, fileSize)];
    int bytesRead = 0;
    while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0) {
        requestStream.Write(buffer, 0, bytesRead);
    }

    // next line never completes                        
    requestStream.Write(postFooterBytes, 0, postFooterBytes.Length);

    // code below is never reached
    Console.WriteLine("Why do I never see this message in the console?");
}

有什么想法吗?

预计到达时间:尝试在最后一个 Write() 之前刷新流,这可能会有所帮助,但没有效果。

再次编辑:添加了using(),以澄清我不是一个完全的白痴。另请注意,这是在 another using() 块内 fileStream

【问题讨论】:

  • 很明显,但是您确定当您使用HttpWebRequest时会发出页脚,对吗? (例如,来自浏览器或 wget)
  • @harpo 我不确定我是否理解。是我发出页脚。
  • 你确定你没有在读取时永远循环吗?
  • Console.WriteLine() 调用是否在 requestStream.Write() 调用之前起作用?
  • 只是为了澄清:程序挂在最后一次写入中,并且没有抛出异常?另外,如果你不写页脚会发生什么?

标签: c# .net stream httpwebrequest


【解决方案1】:

已解决:在 HttpWebRequest 上关闭了 AllowWriteStreamBuffering。看起来当它打开时,无论Write() 调用写入最后一个字节,它都不会返回,直到内部缓冲区被清除。所以最后一个Write() 最终还是参加了比赛,直到我没有耐心为止。

而且由于我最初尝试做的是确定进度,因此关闭缓冲会让事情变得更清晰。

【讨论】:

    【解决方案2】:

    一个常见的问题是忘记关闭请求流。您将看到的症状之一是从未提出过请求。很可能写入确实正在完成,但是由于您没有关闭请求流,因此对 HttpWebRequest.GetResponse() 的调用似乎没有被执行。

    尝试以下方法,看看是否有效果:

    using (var requestStream = myRequest.GetRequestStream())
    {
        // write to the request stream here
    }
    // Now try to get the response.
    

    另一个可能的问题是数据的大小。首先,您确定服务器可以处理 15 MB 的上传吗?其次,如果您在连接速度较慢的情况下执行此操作,则发送 15 MB 可能需要一段时间。我有一个被认为是 1.5 兆比特/秒的“快速”上游连接。最多也就是每秒 0.15 兆字节。发送 15 兆字节需要一分半钟。

    另一种可能性是请求超时。您想查看 HttpWebRequest.TimeoutReadWriteTimeout 属性。

    【讨论】:

    • 上面的代码 sn-p 在 using() 块内,它不是未执行的 HttpWebRequest.GetResponse(),而是最后一次写入下方的任何代码——例如,Console.WriteLine()
    • @David:好的。请参阅我关于尺寸的说明。
    • 那么预期的行为是它似乎可以快速写入所有内容,但在等待它“真正”被写入时挂在最后一个写入调用上?因为这种行为在数百 K 的变化中是一致的——文件数据循环完成,然后页脚挂起。
    • @David:快速编写所有内容并不会让我感到惊讶,因为它可以全部进入内部缓冲区,然后被流出到服务器。为什么页脚写会挂起是一个谜。我想如果帖子页脚很大,那可能会导致问题,但你说它很小。即使超时,我也希望抛出异常。
    • 我认为你是在正确的轨道上。我关闭了AllowWriteStreamBuffering 并且(1)文件写入速度要慢得多,而(2)页脚完成得很好。显然,在内部缓冲区刷新之前写入最后一个字节不会返回。
    【解决方案3】:

    当您构建您的请求时,您的内容长度也应该包括标题,确保它不只是设置为文件长度。 您可以尝试的另一件事是在一切都说完后在流上调用.Flush()。 我不确定 Jim 建议关闭 HttpClient 流的含义,它可能会起作用,但可能会使情况变得更糟。

    使用System.Net.WebClient 是否不够灵活?您可以使用一个不错的UploadFile() 方法。

    【讨论】:

    • 内容长度已经考虑了页眉和页脚,但是谢谢。我尝试在最后一个Write() 之后添加Flush(),但从未达到。
    • 通常在托管代码中,行不会在没有异常或抛出某些东西的情况下变得“无法访问”。您可以尝试在最后一次写入时设置断点,然后查看执行该行后会发生什么吗?您是否曾经从您的 HttpWebRequest 对象中调用过 .GetResponse()
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-01-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-29
    相关资源
    最近更新 更多