2012-12-07 31 views
16

Tôi đang cố tải xuống tệp lớn từ URL công khai. Nó dường như làm việc tốt lúc đầu nhưng 1/10 máy tính dường như thời gian chờ. Nỗ lực ban đầu của tôi là sử dụng WebClient.DownloadFileAsync nhưng vì nó sẽ không bao giờ hoàn thành, tôi đã quay lại sử dụng WebRequest.Create và đọc luồng phản hồi trực tiếp.WebRequest không tải xuống được các tệp lớn (~ 1 GB) đúng cách

Phiên bản sử dụng đầu tiên của tôi WebRequest.Create tìm thấy cùng một vấn đề với tên là WebClient.DownloadFileAsync. Thời gian hoạt động và tệp không hoàn thành.

Phiên bản tiếp theo của tôi đã thêm lần thử lại nếu thời gian tải xuống đã hết. Đây là nó được kỳ lạ. Quá trình tải xuống cuối cùng kết thúc với 1 lần thử lại để kết thúc 7092 byte cuối cùng. Vì vậy, tập tin được tải xuống với chính xác cùng kích thước NHƯNG tệp bị hỏng và khác với tệp nguồn. Bây giờ tôi sẽ mong đợi tham nhũng được trong 7092 byte cuối cùng nhưng đây không phải là trường hợp.

Sử dụng BeyondCompare Tôi đã phát hiện thấy có 2 đoạn byte bị thiếu trong tệp bị hỏng tổng cộng tới 7092 byte bị thiếu! Các byte bị thiếu này là 1CA49FF01E31F380, cách trước khi thời gian tải xuống được khởi động lại và được khởi động lại.

Điều gì có thể xảy ra ở đây? Bất kỳ gợi ý nào về cách theo dõi vấn đề này xa hơn?

Đây là mã được đề cập.

public void DownloadFile(string sourceUri, string destinationPath) 
{ 
    //roughly based on: http://stackoverflow.com/questions/2269607/how-to-programmatically-download-a-large-file-in-c-sharp 
    //not using WebClient.DownloadFileAsync as it seems to stall out on large files rarely for unknown reasons. 

    using (var fileStream = File.Open(destinationPath, FileMode.Create, FileAccess.Write, FileShare.Read)) 
    { 
     long totalBytesToReceive = 0; 
     long totalBytesReceived = 0; 
     int attemptCount = 0; 
     bool isFinished = false; 

     while (!isFinished) 
     { 
      attemptCount += 1; 

      if (attemptCount > 10) 
      { 
       throw new InvalidOperationException("Too many attempts to download. Aborting."); 
      } 

      try 
      { 
       var request = (HttpWebRequest)WebRequest.Create(sourceUri); 

       request.Proxy = null;//http://stackoverflow.com/questions/754333/why-is-this-webrequest-code-slow/935728#935728 
       _log.AddInformation("Request #{0}.", attemptCount); 

       //continue downloading from last attempt. 
       if (totalBytesReceived != 0) 
       { 
        _log.AddInformation("Request resuming with range: {0} , {1}", totalBytesReceived, totalBytesToReceive); 
        request.AddRange(totalBytesReceived, totalBytesToReceive); 
       } 

       using (var response = request.GetResponse()) 
       { 
        _log.AddInformation("Received response. ContentLength={0} , ContentType={1}", response.ContentLength, response.ContentType); 

        if (totalBytesToReceive == 0) 
        { 
         totalBytesToReceive = response.ContentLength; 
        } 

        using (var responseStream = response.GetResponseStream()) 
        { 
         _log.AddInformation("Beginning read of response stream."); 
         var buffer = new byte[4096]; 
         int bytesRead = responseStream.Read(buffer, 0, buffer.Length); 
         while (bytesRead > 0) 
         { 
          fileStream.Write(buffer, 0, bytesRead); 
          totalBytesReceived += bytesRead; 
          bytesRead = responseStream.Read(buffer, 0, buffer.Length); 
         } 

         _log.AddInformation("Finished read of response stream."); 
        } 
       } 

       _log.AddInformation("Finished downloading file."); 
       isFinished = true; 
      } 
      catch (Exception ex) 
      { 
       _log.AddInformation("Response raised exception ({0}). {1}", ex.GetType(), ex.Message); 
      } 
     } 
    } 
} 

Đây là dữ liệu ghi nhận từ tải về tham nhũng:

Request #1. 
Received response. ContentLength=939302925 , ContentType=application/zip 
Beginning read of response stream. 
Response raised exception (System.Net.WebException). The operation has timed out. 
Request #2. 
Request resuming with range: 939295833 , 939302925 
Received response. ContentLength=7092 , ContentType=application/zip 
Beginning read of response stream. 
Finished read of response stream. 
Finished downloading file. 
+1

Tôi có thể nghĩ hai điều trên đỉnh đầu. a) Tăng thời gian chờ của bạn cho các tệp lớn (nếu có thể) b) mã hóa và giải mã dữ liệu của bạn có bị hỏng không? Tôi đã có vấn đề này trên một dự án khác nhau mà tôi từng có. Cố gắng mã hóa nó bằng cách sử dụng UTF-8 – Steven

+0

Nó không phải là một vấn đề mã hóa, nó là một blob nhị phân (tập tin zip). – Spish

+5

Âm thanh với tôi bạn đang cố gắng gỡ lỗi một lỗi máy chủ trên đầu dây sai. –

Trả lời

0

này là phương pháp tôi thường sử dụng, nó đã không thất bại cho tôi cho đến nay cho cùng một loại tải mà bạn cần. Hãy thử sử dụng mã của tôi để thay đổi mã của bạn một chút và xem điều đó có giúp ích gì không.

if (!Directory.Exists(localFolder)) 
{ 
    Directory.CreateDirectory(localFolder); 
} 


try 
{ 
    HttpWebRequest httpRequest = (HttpWebRequest)WebRequest.Create(Path.Combine(uri, filename)); 
    httpRequest.Method = "GET"; 

    // if the URI doesn't exist, exception gets thrown here... 
    using (HttpWebResponse httpResponse = (HttpWebResponse)httpRequest.GetResponse()) 
    { 
     using (Stream responseStream = httpResponse.GetResponseStream()) 
     { 
      using (FileStream localFileStream = 
       new FileStream(Path.Combine(localFolder, filename), FileMode.Create)) 
      { 
       var buffer = new byte[4096]; 
       long totalBytesRead = 0; 
       int bytesRead; 

       while ((bytesRead = responseStream.Read(buffer, 0, buffer.Length)) > 0) 
       { 
        totalBytesRead += bytesRead; 
        localFileStream.Write(buffer, 0, bytesRead); 
       } 
      } 
     } 
    } 
} 
catch (Exception ex) 
{   
    throw; 
} 
0

Bạn nên thay đổi cài đặt thời gian chờ. Dường như có hai vấn đề thời gian chờ có thể xảy ra:

  • Hết giờ phía máy khách - hãy thử thay đổi thời gian chờ trong WebClient. Tôi tìm thấy tải tập tin lớn đôi khi tôi cần phải làm điều đó.
  • Hết thời gian chờ phía máy chủ - hãy thử thay đổi thời gian chờ trên máy chủ. Bạn có thể xác thực đây là sự cố khi sử dụng ứng dụng khách khác, ví dụ: PostMan
0

Đối với tôi, phương pháp của bạn về cách đọc tệp bằng bộ đệm trông rất lạ. Có lẽ vấn đề là, mà bạn làm

while(bytesRead > 0) 

gì nếu vì một lý do, dòng doesnt trả lại bất kỳ byte tại một số điểm nhưng nó vẫn chưa được hoàn tất tải về, sau đó nó sẽ thoát khỏi vòng lặp và không bao giờ đến trở lại. Bạn sẽ nhận được Content-Length và tăng một biến totalBytesReceived bởi bytesRead. Cuối cùng, bạn thay đổi vòng lặp thành

while(totalBytesReceived < ContentLength) 
Các vấn đề liên quan