2009-04-27 9 views
8

私は非同期的にこのようWebRequestクラス使用してURLからイメージをダウンロードします。winformsを使用してC#でダウンロードの進行状況を示すWebから画像をダウンロードするには?

public void Download(string url) 
{ 
    byte[] buffer = new byte[0x1000]; 
    WebRequest request = HttpWebRequest.Create(url); 
    request.Method = "GET"; 
    request.ContentType = "image/gif"; 

    request.BeginGetResponse(result => 
    { 
    WebRequest webRequest = result.AsyncState as WebRequest; 

    WebResponse response = webRequest.EndGetResponse(result); 
    ReadState readState = new ReadState() 
    { 
     Response = response.GetResponseStream(), 
     AccumulatedResponse = new MemoryStream(), 
     Buffer = buffer, 
    }; 

    readState.Response.BeginRead(buffer, 0, 
     readState.Buffer.Length, ReadCallback, readState); 
    }, request); 
} 

public void ReadCallback(IAsyncResult result) 
{ 
    ReadState readState = result.AsyncState as ReadState; 
    int bytesRead = readState.Response.EndRead(result); 
    if(bytesRead > 0) 
    { 
    readState.AccumulatedResponse.BeginWrite(readState.Buffer, 0, bytesRead, writeResult => 
    { 
     readState.AccumulatedResponse.EndWrite(writeResult); 
     readState.Response.BeginRead(readState.Buffer, 0, readState.Buffer.Length, ReadCallback, readState); 
    }, null); 
    } 
    else 
    { 
    readState.AccumulatedResponse.Flush(); 
    readState.Response.Close(); 
    pictureBox1.Image = Image.FromStream(readState.AccumulatedResponse); 
    } 
} 

public class ReadState 
{ 
    public Stream Response { get; set; } 
    public Stream AccumulatedResponse { get; set; } 
    public byte[] Buffer { get; set; } 
} 

をし、それは大丈夫動作しますが、ブラウザがそうであるように私は、ダウンロードの進行状況を表示したいと思い、そしてときにのみ、それを表示しません終了する。

それは私が絵が、それはいくつかのデータを持っているにもかかわらず、無効であることを例外を取得完了する前に、私は

pictureBox1.Image = Image.FromStream(readState.AccumulatedResponse); 

を行う場合。 とにかく部分データを表示していますか?

+1

画像が有効でない場合、PictureBoxコントロールに関する限り、不運になります。限り、進捗状況...ファイルの大きさを知るために応答のContentLengthを確認してください。 –

答えて

5

JPEGには、「プログレッシブJPEG」と呼ばれる特別なエンコードモードがあります。このモードでは、データは段階的に詳細な複数のパスで圧縮されます。 Windows 7にはbuilt-in supportがあります。

+2

通知彼はimage/gifにコード化されているので、おそらく助けにならないでしょう –

+2

Windows 7はGIFもサポートしています:http://msdn.microsoft.com/en-us/library/dd408863(VS.85).aspx# _pnggifprogressivedecoding –

+0

詳細はこちら:http://ja.wikipedia.org/wiki/Interlace_(bitmaps) – scottm

3

要求を開始するときは、期待する合計バイト数を示すWebResponse.ContentLengthプロパティを確認します。次に、ReadCallbackメソッドで読み取られた合計バイト数を記録します。残りは明白でなければなりません。 :)

[編集]おっと、私は質問を再読した。それはあなたが望んでいたものではなかった。私はまだ誰かがそれから恩恵を受けるかもしれないので、これを残している。

2

.NETフレームワークの組み込みメソッドを使用して管理するとは思わないでしょう。まず、フルイメージを読み込んで表示するからです。部分的にダウンロードされたイメージを表示するのをサポートする他のライブラリを見つけるか、自分でパーサーを書く必要があります。

4

ブラウザがそうであるように、私は、ダウンロード の進行状況を表示したいと思い、そして それが終了した場合にのみ表示しません。

  1. 使用WebClient.DownloadDataAsync

2つのオプションがあります。これにより、DownloadProgressChangedを介して進捗イベントが発生し、DownloadDataCompletedイベントを介してデータがいつ利用可能になるかを最終的に通知します。その時点で、例えばPictureBoxに画像を割り当てることができます。

  • 最終的にPictureBoxコントロールに表示する画像をダウンロードする場合は、PictureBox.LoadAsyncと一緒に行くほうが簡単かもしれません。これもまた、完了時にLoadProgressChangedイベント、最後にLoadCompletedイベントを介して進行状況の更新を提供します。

  • 4

    部分的なダウンロードではなく、PictureBoxコントロールに問題があります。

    IEが部分的な画像を表示できるように、WebBrowserControlを使用するのがハックです。

    2

    これはおそらく可能ですが、gifファイルの構造に関する追加知識が必要になります。 Wotsit.orgには、gif構造ドキュメントへのリンクがいくつか用意されています。

    一般的なアプローチは、ブロックターミネータの終わりが見つかるまで、蓄積されたデータ全体を取り出し、最後から検索し直すことです。この最後の有効なブロックとストリームの終わりとの間のデータは部分的にしか完成せず、迷惑データとみなされなければならない。それを削除して、ファイルの末尾ブロックをストリームに追加したいとします。次に、この編集されたストリームをPictureBoxに読み込むことができるはずです。

    1

    定期的に呼び出される非同期Webダウンロードリクエストで使用できるイベントがあり、ProgressBarコントロールを直接更新することができます。ここで私は、このイベントを使用しました方法の例です:

    delegate void SetProgressDelegate(int percentComplete); 
        /// <summary> 
        /// A thread-safe method for updating the file download progress bar. 
        /// </summary> 
        /// <param name="bytesReceived"></param> 
        /// <param name="totalBytes"></param> 
        void SetDownloadProgress(int percentComplete) 
        { 
         if (this.InvokeRequired) 
         { 
          SetProgressDelegate d = new SetProgressDelegate(SetDownloadProgress); 
          this.Invoke(d, new object[] { percentComplete }); 
         } 
         else 
         { 
          this.progressFileDownload.Value = percentComplete; 
         } 
        } 
        /// <summary> 
        /// Event handler to update the progress bar during file download. 
        /// </summary> 
        /// <param name="sender"></param> 
        /// <param name="e"></param> 
        void web_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e) 
        { 
         SetDownloadProgress(e.ProgressPercentage); 
        } 
    

    そして、ここでは、私がイベントを配線し、ダウンロードを開始方法は次のとおりです。

      WebClient web = new WebClient(); 
          web.DownloadFileCompleted += new AsyncCompletedEventHandler(web_DownloadFileCompleted); 
          web.DownloadProgressChanged += new DownloadProgressChangedEventHandler(web_DownloadProgressChanged); 
          web.DownloadFileAsync(sourceUri, destinationFileName); 
    

    あなたの解決策は私のに対し、メモリに直接ファイルを読み込みそれをディスク上のファイルに保存するので、この解決法はあなたのために働くかもしれません。進捗状況の表示が重要である場合、この方法は機能し、一時ファイルにダウンロードしてから、そのファイルが完了したらイメージコントロールにロードすることができます。

    関連する問題