2011-11-08 14 views
0

メソッドでファイルをダウンロードし、最初のメソッドで変数に格納されているデータを使用してそのファイルを処理します。 DownloadFileAsyncを使用することができますが、DownloadFileCompletedメソッドで作業を続行する必要があります。グローバルなものを宣言して代わりに使用しない限り、変数はそこから到達できません。私は考えます)。progressbarでファイルをダウンロード

私はグーグルで、ファイルを手作業でダウンロードして別の方法で見つけました。それは私にとって非常に完璧です。私が知りたがっているのは、もっと簡単な私の問題に対する他の方法や解決策があるかどうかです。

それとも、イベントで遊んで、より良い私に合った何かを達成できるかどうか:)

ああ、あなたはそれのより良いタイトルを見つけた場合、私は1つを考えることができませんでした私の質問を変更してください。

+0

"変数はそこから到達できません"ということは何ですか? DownloadFileCompletedを使用すると、完全にグローバル変数に到達することができます –

+0

@mekici **私はいくつかのグローバルなものを宣言しない限り、**と言っています。 – fgblomqvist

+0

ahh ok :)あなたはファイルasyncをダウンロードすることをお勧めします。多分あなたはクラスとグローバルリストを作成することができますオブジェクトを作成し、そのリストをDownloadFileCompletedメソッドに追加することができます –

答えて

3

プログレスバーを更新するには、1つずつ修正する必要があります。このコードはトリックです。

public class WebDownloader 
{ 
    private static readonly ILog log = LogManager.GetLogger(typeof(WebDownloader)); 

    public delegate void DownloadProgressDelegate(int percProgress); 

public static void Download(string uri, string localPath, DownloadProgressDelegate progressDelegate) 
    { 
     long remoteSize; 
     string fullLocalPath; // Full local path including file name if only directory was provided. 

     log.InfoFormat("Attempting to download file (Uri={0}, LocalPath={1})", uri, localPath); 

     try 
     { 
      /// Get the name of the remote file. 
      Uri remoteUri = new Uri(uri); 
      string fileName = Path.GetFileName(remoteUri.LocalPath); 

      if (Path.GetFileName(localPath).Length == 0) 
       fullLocalPath = Path.Combine(localPath, fileName); 
      else 
       fullLocalPath = localPath; 

      /// Have to get size of remote object through the webrequest as not available on remote files, 
      /// although it does work on local files. 
      using (WebResponse response = WebRequest.Create(uri).GetResponse()) 
      using (Stream stream = response.GetResponseStream()) 
       remoteSize = response.ContentLength; 

      log.InfoFormat("Downloading file (Uri={0}, Size={1}, FullLocalPath={2}).", 
       uri, remoteSize, fullLocalPath); 
     } 
     catch (Exception ex) 
     { 
      throw new ApplicationException(string.Format("Error connecting to URI (Exception={0})", ex.Message), ex); 
     } 

     int bytesRead = 0, bytesReadTotal = 0; 

     try 
     { 
      using (WebClient client = new WebClient()) 
      using (Stream streamRemote = client.OpenRead(new Uri(uri))) 
      using (Stream streamLocal = new FileStream(fullLocalPath, FileMode.Create, FileAccess.Write, FileShare.None)) 
      { 
       byte[] byteBuffer = new byte[1024 * 1024 * 2]; // 2 meg buffer although in testing only got to 10k max usage. 
       int perc = 0; 
       while ((bytesRead = streamRemote.Read(byteBuffer, 0, byteBuffer.Length)) > 0) 
       { 
        bytesReadTotal += bytesRead; 
        streamLocal.Write(byteBuffer, 0, bytesRead); 
        int newPerc = (int)((double)bytesReadTotal/(double)remoteSize * 100); 
        if (newPerc > perc) 
        { 
         log.InfoFormat("...Downloading (BytesRead={0}, Perc={1})...", bytesReadTotal, perc); 
         perc = newPerc; 
         if (progressDelegate != null) 
          progressDelegate(perc); 
        } 
       } 
      } 
     } 
     catch (Exception ex) 
     { 
      throw new ApplicationException(string.Format("Error downloading file (Exception={0})", ex.Message), ex); 
     } 

     log.InfoFormat("File successfully downloaded (Uri={0}, BytesDownloaded={1}/{2}, FullLocalPath={3}).", 
      uri, bytesReadTotal, remoteSize, fullLocalPath); 
    } 
} 

このコードを明らかに同期して実行するには、スレッドをスピンオフする必要があります。

Task.Factory.StartNew(_ => Download(...)); 
+0

+1書式付きテキストの付いた針の段落がない自己説明コードの場合+1。 – pjvds

+0

その素晴らしいコードをありがとう! 私はそれを通り抜けていくつかのことを学びました;) – fgblomqvist

+0

うれしいですね。私はかなり前にそれを書いていましたが、今すぐ書き直していました。Reactive Extensionsを使って別の方法でやります。なぜ私がファイルサイズを取得するためにWebリクエストを使用しているのかについてのコメントは、少し不明です - ファイルサイズを取得するための他の方法がさまざまな状況で機能しないため、私はこれを行います。 – DanH

関連する問題