2010-11-21 14 views
9

Tôi thấy rằng HttpWebRequest Tải lên của tôi là thất bại vào phút cuối của tải lên ... như thể hiện trong this video @ScreenrWeb Yêu cầu/Upload Không ít Rất End

Mã của tôi là như dưới đây

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); 
    } 

Tôi không biết nếu bạn cần thêm mã, tôi chỉ không muốn mã spam ở đây. ngoại lệ bên dưới

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: 

Thông báo ngoại lệ bên trong "Không thể đóng luồng cho đến khi tất cả byte được ghi". Nhưng tôi havent gần bất kỳ dòng trong vòng này có tôi?

+0

+1 cho nội dung video :-) –

+0

@Darin Dimitrov, tôi không giỏi giải thích điều gì đó, vì vậy tôi nghĩ một video sẽ có giá trị 2k từ ... một cái gì đó không ai sẽ bận tâm đọc ... lol –

Trả lời

15

Vâng, bạn đang đóng luồng bằng cách đặt nó trong tuyên bố using - nhưng bạn nên sẽ đóng cửa, do đó, đó không phải là vấn đề.

Một vài điểm để bắt đầu với:

  • tôi sẽ không sử dụng một BinaryWriter đây. Nó không mua cho bạn bất cứ điều gì. Viết trực tiếp vào luồng.
  • Nếu memStream là một MemoryStream, bạn có thể sử dụng WriteTo:

    using (var reqStream = req.GetRequestStream()) 
    { 
        memStream.WriteTo(reqStream); 
    } 
    

    Điều đó có nghĩa bạn sẽ không nhận chẩn đoán của bạn, nhưng nó làm cho đoạn code đơn giản hơn :)

Bây giờ, về những gì đang xảy ra ... đoán của bạn là bạn đang nhận được ngoại lệ trong cuộc gọi đến Write, nhưng ngoại lệ đó đang được thay thế hiệu quả bằng ngoại lệ bị ném bằng cách đóng luồng.

Tôi có ý tưởng tại sao ngoại lệ cũng có thể bị ném ...

Bạn có đặt độ dài nội dung ở bất kỳ đâu không? Bởi vì bạn có lẽ sẽ vượt qua nó. Nhìn vào dòng này:

reqWriter.Write(buffer); 

này được viết toàn bộ đệm trên mỗi lặp của vòng lặp, bỏ qua bao nhiêu dữ liệu bạn vừa đọc. Bạn đã gán số byte được đọc vào biến read, nhưng sau đó bạn sẽ không bao giờ sử dụng giá trị đó. Bạn có thể sửa lỗi này bằng cách thay đổi nó thành

reqWriter.Write(buffer, 0, read); 

... nhưng cá nhân tôi thì không. Tôi muốn hoặc chỉ cần sử dụng MemoryStream.WriteTohoặc ghi trực tiếp vào luồng yêu cầu ... như tôi đã nói trước đây, BinaryWriter không thực sự mua cho bạn bất kỳ thứ gì.

Dù sao, trong mã hiện tại của bạn cho mọi yêu cầu, bạn sẽ cố viết nhiều 25600 byte, bất kể độ dài nội dung của bạn là bao nhiêu. Tôi sẽ không ngạc nhiên nếu luồng yêu cầu nhận thấy điều đó và đã ném một ngoại lệ. Giả sử chúng ta có 30000 byte dữ liệu.Tôi nghi ngờ trình tự đi một cái gì đó như thế này:

  • Content chiều dài được thiết lập để 30000
  • Lấy dòng và nhập bằng tuyên bố
  • đọc 25600 byte từ dòng bộ nhớ
  • Write 25600 byte ra: dòng xác nhận rằng đúng là
  • Đọc 4400 byte từ luồng bộ nhớ (nghĩa là tất cả dữ liệu còn lại)
  • Cố gắng viết 25600 byte: luồng ngay lập tức quyết định đó là không hợp lệ, và ném một IOException
  • Các ngầm finally khối tuyên bố using sau đó disposes suối, mà đóng nó
  • Thông báo dòng mà chỉ có 25600 byte đã được viết thành công, đó là chưa đủ, do đó ném một ngoại lệ

Đây là một điều khiến thư viện đưa ra ngoại lệ từ Dispose ... nhưng giả sử tôi đúng, nó cung cấp cho bạn sự cố thú vị mà bạn đã từng cố gắng viết nhiều quá ít dữ liệu :)

+0

Bạn hiểu đúng 'reqWriter.Write (buffer, 0, read)' đã giải quyết được vấn đề. Như bạn đã nói, trong lần vượt qua cuối cùng khi có ít hơn 25600byte, nó đã cố gắng viết 25600 byte + chiều dài nội dung được đặt, vì vậy ngoại lệ xảy ra. Ngoài ra tôi muốn theo dõi tiến độ, 'memStream.WriteTo (reqStream)' sẽ cho tôi không có cách nào để theo dõi tiến trình? –

+0

@jiewmeng: Vâng, một phần phụ thuộc vào việc luồng yêu cầu có bị lưu vào bộ đệm hay không. Nếu có, thì bạn sẽ không thực sự theo dõi tiến độ. Nếu không, bạn có thể giữ mã hiện tại của mình nhưng không có 'reqWriter' - chỉ cần ghi trực tiếp vào luồng thay vào đó. –

4

Bạn không thể ghi "bộ đệm" kể từ khi kết thúc "bộ đệm" không chứa 20k giá trị của dữ liệu.

Vì vậy, khi bạn thực hiện memStream.Read nó trả về số byte thực sự đọc. Bạn cần sử dụng kiến ​​thức/thông tin đó khi viết.

reqWriter.Write(buffer, 0, read); 
+1

Vâng, 'bộ đệm' sẽ * luôn * chứa 25600 byte dữ liệu. Nó không giống như bản thân mảng phát triển và co lại. Chúng có thể không phải là * rất hữu ích * byte. –

+0

đúng, nhưng một phần của bộ đệm là những gì anh ta cần phải viết và bao nhiêu được xác định bởi bao nhiêu byte đã được đọc. –

+0

@Shiv: Tuyệt đối - nó chỉ đơn thuần là một nitpick giữa "không chứa 20k dữ liệu" và "không chứa 20k dữ liệu * phải được viết *". –

Các vấn đề liên quan