2017-06-06 93 views
3

我正在使用WebClient下載文件。 但是,當它嘗試下載大於50mb大小的大文件時,會發生一些腥意,下載將在39kb之後完成,並且不會將其下載到最後。 任何人都知道可能是什麼問題?如果超過50MB,WebClient不能完全下載文件

using (webClient = new WebClient()) 
{ 
    webClient.Proxy = null; 
    webClient.Headers.Add("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)"); 
    webClient.DownloadFileCompleted += new AsyncCompletedEventHandler(Completed); 
    webClient.DownloadProgressChanged += new DownloadProgressChangedEventHandler(ProgressChanged); 

    // The variable that will be holding the url address (making sure it starts with http://) 
    Uri URL = urlAddress.StartsWith("http://", StringComparison.OrdinalIgnoreCase) ? new Uri(urlAddress) : new Uri("http://" + urlAddress); 

    // Start the stopwatch which we will be using to calculate the download speed 
    sw.Start(); 

    try 
    { 
     // Start downloading the file 
     webClient.DownloadFileAsync(URL, _mainWindow.outputDirComboBox.SelectedItem.ToString() + "\\" + _compressedClientFileDownloadRelativePath, new List<object> 
     { 
      _compressedClientFileDownloadRelativePath, 
      _decompressedClientFileDownloadRelativePath, 
      _lastDownloadedFilePath, 
      _compressedSize, 
      _lastCompressedFilePartRelativePath, 
      _filePartsRelativePath, 
      urlAddress, 
      _clientFilePack, 
      _clientFile 
     }); 
    } 
    catch (Exception ex) 
    { 
     MessageBox.Show(ex.Message); 
    } 
} 

DownloadFileCompleted只檢查錯誤,當它完成但沒有任何錯誤報告正在進行時。只有完成下載彷彿下載大小僅爲39KB

EDIT1: 雖然挖我會在這裏結束:Downloading Large Google Drive files with WebClient in C#

看起來像谷歌雲端硬盤,某種形式的確認鏈接,但即時通訊尚未能知道如何把所有的工作放在一起。

EDIT2: 我剛剛確認,該39KB的HTML頁面確認

+1

在您完成使用之前,您正在處置Web客戶端,您預期會發生什麼? –

+0

配置不會改變任何問題解決方案。 我試圖從Mega或谷歌驅動器下載文件,但沒有直接鏈接訪問API,這可能是問題嗎?因爲我只是試圖從speedtest下載:speedtest.tele2.net/100MB.zip,它的工作原理我不想爲我的公共應用程序提供谷歌驅動器或大型api證書,因爲它看起來像這些雲服務器限制爲每次50MB與webclient下載 – Supreme

+0

檢查此https://stackoverflow.com/questions/2269607/how-to-programmatically-download-a-large-file-in-c-sharp –

回答

2

你必須等待webClient.DownloadFileAsync過程

否則你的執行掉下來的處置命令時,該文件仍然在下載

例如:

public class DownloadManager 
{ 
    public void DownloadFile(string sourceUrl, string targetFolder) 
    { 
     WebClient downloader = new WebClient(); 
      // fake as if you are a browser making the request. 
     downloader.Headers.Add("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0)"); 
     downloader.DownloadFileCompleted += new AsyncCompletedEventHandler(Downloader_DownloadFileCompleted); 

     downloader.DownloadFileAsync(new Uri(sourceUrl), targetFolder); 

    } 

    private void Downloader_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e) 
    { 
      // display completion status. 
     if (e.Error != null) 
      Console.WriteLine(e.Error.Message); 
     else 
      Console.WriteLine("Download Completed!!!"); 
    } 
} 
+0

不會更改任何從代碼中刪除處置。 編輯:正如我所說,它從50MB下載較低的文件,但對 – Supreme

+0

以上的文件下載是的,因爲你進入USING,嘗試我的代碼段plz –

+0

完全按照你告訴我改變了代碼仍然不工作。 我試圖從Mega或谷歌驅動器下載文件沒有API直接鏈接訪問,可能是問題?〜 因爲我只是試圖從speedtest下載:http://speedtest.tele2.net/100MB.zip和它運作良好 我不想爲我的公共應用程序提供谷歌驅動器或大型api證書,因爲它看起來像這些雲服務器限制爲每次下載與webclient 50mb最大 – Supreme

2

感謝大家!

檢查這個問題後: Downloading Large Google Drive files with WebClient in C# 我搜索從谷歌獲得更大的文件和C#的車程,發現this

using System; 
using System.IO; 
using System.Net; 

public static class FileDownloader 
{ 
    private const string GOOGLE_DRIVE_DOMAIN = "drive.google.com"; 
    private const string GOOGLE_DRIVE_DOMAIN2 = "https://drive.google.com"; 

    // Normal example: FileDownloader.DownloadFileFromURLToPath("http://example.com/file/download/link", @"C:\file.txt"); 
    // Drive example: FileDownloader.DownloadFileFromURLToPath("http://drive.google.com/file/d/FILEID/view?usp=sharing", @"C:\file.txt"); 
    public static FileInfo DownloadFileFromURLToPath(string url, string path) 
    { 
     if(url.StartsWith(GOOGLE_DRIVE_DOMAIN) || url.StartsWith(GOOGLE_DRIVE_DOMAIN2)) 
      return DownloadGoogleDriveFileFromURLToPath(url, path); 
     else 
      return DownloadFileFromURLToPath(url, path, null); 
    } 

    private static FileInfo DownloadFileFromURLToPath(string url, string path, WebClient webClient) 
    { 
     try 
     { 
      if(webClient == null) 
      { 
       using(webClient = new WebClient()) 
       { 
        webClient.DownloadFile(url, path); 
        return new FileInfo(path); 
       } 
      } 
      else 
      { 
       webClient.DownloadFile(url, path); 
       return new FileInfo(path); 
      } 
     } 
     catch(WebException) 
     { 
      return null; 
     } 
    } 

    // Downloading large files from Google Drive prompts a warning screen and 
    // requires manual confirmation. Consider that case and try to confirm the download automatically 
    // if warning prompt occurs 
    private static FileInfo DownloadGoogleDriveFileFromURLToPath(string url, string path) 
    { 
     // You can comment the statement below if the provided url is guaranteed to be in the following format: 
     // https://drive.google.com/uc?id=FILEID&export=download 
     url = GetGoogleDriveDownloadLinkFromUrl(url); 

     using(CookieAwareWebClient webClient = new CookieAwareWebClient()) 
     { 
      FileInfo downloadedFile; 

      // Sometimes Drive returns an NID cookie instead of a download_warning cookie at first attempt, 
      // but works in the second attempt 
      for(int i = 0; i < 2; i++) 
      { 
       downloadedFile = DownloadFileFromURLToPath(url, path, webClient); 
       if(downloadedFile == null) 
        return null; 

       // Confirmation page is around 50KB, shouldn't be larger than 60KB 
       if(downloadedFile.Length > 60000) 
        return downloadedFile; 

       // Downloaded file might be the confirmation page, check it 
       string content; 
       using(var reader = downloadedFile.OpenText()) 
       { 
        // Confirmation page starts with <!DOCTYPE html>, which can be preceeded by a newline 
        char[] header = new char[20]; 
        int readCount = reader.ReadBlock(header, 0, 20); 
        if(readCount < 20 || !(new string(header).Contains("<!DOCTYPE html>"))) 
         return downloadedFile; 

        content = reader.ReadToEnd(); 
       } 

       int linkIndex = content.LastIndexOf("href=\"/uc?"); 
       if(linkIndex < 0) 
        return downloadedFile; 

       linkIndex += 6; 
       int linkEnd = content.IndexOf('"', linkIndex); 
       if(linkEnd < 0) 
        return downloadedFile; 

       url = "https://drive.google.com" + content.Substring(linkIndex, linkEnd - linkIndex).Replace("&amp;", "&"); 
      } 

      downloadedFile = DownloadFileFromURLToPath(url, path, webClient); 

      return downloadedFile; 
     } 
    } 

    // Handles 3 kinds of links (they can be preceeded by https://): 
    // - drive.google.com/open?id=FILEID 
    // - drive.google.com/file/d/FILEID/view?usp=sharing 
    // - drive.google.com/uc?id=FILEID&export=download 
    public static string GetGoogleDriveDownloadLinkFromUrl(string url) 
    { 
     int index = url.IndexOf("id="); 
     int closingIndex; 
     if(index > 0) 
     { 
      index += 3; 
      closingIndex = url.IndexOf('&', index); 
      if(closingIndex < 0) 
       closingIndex = url.Length; 
     } 
     else 
     { 
      index = url.IndexOf("file/d/"); 
      if(index < 0) // url is not in any of the supported forms 
       return string.Empty; 

      index += 7; 

      closingIndex = url.IndexOf('/', index); 
      if(closingIndex < 0) 
      { 
       closingIndex = url.IndexOf('?', index); 
       if(closingIndex < 0) 
        closingIndex = url.Length; 
      } 
     } 

     return string.Format("https://drive.google.com/uc?id={0}&export=download", url.Substring(index, closingIndex - index)); 
    } 
} 

// Web client used for Google Drive 
public class CookieAwareWebClient : WebClient 
{ 
    private class CookieContainer 
    { 
     Dictionary<string, string> _cookies; 

     public string this[Uri url] 
     { 
      get 
      { 
       string cookie; 
       if(_cookies.TryGetValue(url.Host, out cookie)) 
        return cookie; 

       return null; 
      } 
      set 
      { 
       _cookies[url.Host] = value; 
      } 
     } 

     public CookieContainer() 
     { 
      _cookies = new Dictionary<string, string>(); 
     } 
    } 

    private CookieContainer cookies; 

    public CookieAwareWebClient() : base() 
    { 
     cookies = new CookieContainer(); 
    } 

    protected override WebRequest GetWebRequest(Uri address) 
    { 
     WebRequest request = base.GetWebRequest(address); 

     if(request is HttpWebRequest) 
     { 
      string cookie = cookies[address]; 
      if(cookie != null) 
       ((HttpWebRequest) request).Headers.Set("cookie", cookie); 
     } 

     return request; 
    } 

    protected override WebResponse GetWebResponse(WebRequest request, IAsyncResult result) 
    { 
     WebResponse response = base.GetWebResponse(request, result); 

     string[] cookies = response.Headers.GetValues("Set-Cookie"); 
     if(cookies != null && cookies.Length > 0) 
     { 
      string cookie = ""; 
      foreach(string c in cookies) 
       cookie += c; 

      this.cookies[response.ResponseUri] = cookie; 
     } 

     return response; 
    } 

    protected override WebResponse GetWebResponse(WebRequest request) 
    { 
     WebResponse response = base.GetWebResponse(request); 

     string[] cookies = response.Headers.GetValues("Set-Cookie"); 
     if(cookies != null && cookies.Length > 0) 
     { 
      string cookie = ""; 
      foreach(string c in cookies) 
       cookie += c; 

      this.cookies[response.ResponseUri] = cookie; 
     } 

     return response; 
    } 
} 

隨着該計算器問題+這個GitHub的代碼,我的理解是與這兩個問題有關因爲當文件大於50mb時,Google會發送確認頁面。因此,在實現該github代碼後,現在可以使用我的webClient下載大文件。