我发现我的HTTPWebRequest上传在上传的最后阶段失败了...如 this video @Screenr 所示

我的代码如下

using (var reqStream = req.GetRequestStream())
{
    BinaryWriter reqWriter = new BinaryWriter(reqStream);
    byte[] buffer = new byte[25600]; // 20KB Buffer
    int read = 0, bytesRead = 0;
    while ((read = memStream.Read(buffer, 0, buffer.Length)) > 0) {
        reqWriter.Write(buffer); // at the very last loop, this line causes the error
        bytesRead += read;
        Debug.WriteLine("Percent Done: " + ((double)bytesRead / memStream.Length * 100) + "% " + DateTime.Now);
    }

我不知道您是否需要更多代码,我只是不想在此处发送垃圾邮件。以下异常(exception)
System.Net.WebException was caught
  Message=The request was aborted: The request was canceled.
  Source=System
  StackTrace:
       at System.Net.ConnectStream.CloseInternal(Boolean internalCall, Boolean aborting)
       at System.Net.ConnectStream.System.Net.ICloseEx.CloseEx(CloseExState closeState)
       at System.Net.ConnectStream.Dispose(Boolean disposing)
       at System.IO.Stream.Close()
       at System.IO.Stream.Dispose()
       at QuickImageUpload.ViewModels.ShellViewModel.UploadImage(String filename, String contentType, Byte[] image) in D:\Projects\QuickImageUpload\QuickImageUpload\ViewModels\ShellViewModel.cs:line 190
  InnerException: System.IO.IOException
       Message=Cannot close stream until all bytes are written.
       Source=System
       StackTrace:
            at System.Net.ConnectStream.CloseInternal(Boolean internalCall, Boolean aborting)
       InnerException:

注意内部异常“在写入所有字节之前无法关闭流”。但是我还没有关闭此循环中的任何流吗?

最佳答案

好吧,您正在通过将流放在using语句中来关闭流-但您应该将其关闭,因此这不太可能成为问题。

首先要注意以下几点:

  • 在这里我不会使用BinaryWriter。它什么都没买。直接写到流中。
  • 如果memStreamMemoryStream,则可以使用WriteTo:
    using (var reqStream = req.GetRequestStream())
    {
        memStream.WriteTo(reqStream);
    }
    

    这意味着您将无法获得诊断信息,但是它确实使代码更简单:)

  • 现在,关于正在发生的事情...我的猜测是,您在对Write的调用中遇到了一个异常,但是该异常已被关闭流抛出的异常有效地替换了。

    我有一个主意,为什么也可能引发异常...

    您是否在任何地方设置内容长度?因为您可能正在解决它。看这行:
    reqWriter.Write(buffer);
    

    这是在循环的每次迭代中写出整个缓冲区,而忽略了您刚刚读取的数据量。您已经分配了读取到变量read中的字节数,但是您再也不会使用该值了。您可以通过将其更改为
    reqWriter.Write(buffer, 0, read);
    

    ...但是我个人不会。我要么只是使用MemoryStream.WriteTo,要么直接写到请求流中……就像我之前说的那样,BinaryWriter实际上并没有为您买任何东西。

    无论如何,在当前代码中,对于每个请求,无论内容长度如何,都将尝试写入25600字节的倍数。如果请求流注意到并抛出异常,我不会感到惊讶。假设我们有30000字节的数据。我怀疑序列是这样的:
  • 内容长度设置为30000
  • 获取流并使用语句
  • 输入
  • 从内存流
  • 读取25600字节
  • 写出25600字节:流验证那是正确的
  • 从内存流中读取4400字节(即所有剩余数据)
  • 尝试写入25600字节:流立即确定这是无效的,并抛出IOException
  • 然后,finally语句的隐式using块处理流,将其关闭
  • 流注意到仅成功写入了25600字节,这还不够,因此引发异常

  • 正是这种情况使库从Dispose抛出异常是一个坏主意...但是假设我是对的,这确实带来了一个有趣的问题,即您同时尝试写入过多和过少的数据:)

    10-08 03:28