繁体   English   中英

如何使用winforms从网上下载显示下载进度的图像?

[英]How to download an image from web showing the progress of the download in c# using winforms?

我使用WebRequest以这种方式异步下载URL中的图像:

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

在它完成之前,我得到一个例外,即图片无效,即使它有一些数据。 反正有没有显示部分数据?

JPEG具有一种称为“渐进式JPEG”的特殊编码模式,其中数据在逐步更高细节的多次传递中被压缩。 Windows 7 内置了对此的支持

我希望像浏览器一样显示下载的进度,而不是仅在完成时显示。

您有两种选择:

  1. 使用WebClient.DownloadDataAsync 这将通过提高进度事件DownloadProgressChanged并提供当数据通过可用的最终通知DownloadDataCompleted事件。 此时,您可以将图像分配给PictureBox

  2. 如果您正在下载图像的最终显示PictureBox控件,然后它甚至可能是更容易只是去PictureBox.LoadAsync 这也将通过其LoadProgressChanged事件提供进度更新,最后在完成时提供LoadCompleted

你有PictureBox控件的问题,而不是局部下载。

黑客就是使用WebBrowserControl,因为IE能够显示部分图像。

当您开始请求时,请检查WebResponse.ContentLength属性,该属性应该为您提供预期的总字节数。 然后跟踪ReadCallback方法中读取的总字节数。 其余应该是显而易见的。 :)

[编辑]哎呀,我重新阅读了这个问题,这不是你想要的。 我仍然会离开这个,以防有人可能从中受益。

我不认为您将使用.NET框架的内置方法来管理它,因为它们将首先读取完整的图像然后显示它。 您需要找到一些支持显示部分下载图像的其他库或自己编写解析器。

你可以这样做,但是,它需要一些关于gif文件结构的额外知识。 Wotsit.org有几个gif结构文档的链接,可以帮助您入门。

一般方法是获取总累积数据,并从最后搜索,直到找到块终止符的结尾。 最后一个有效块和流结束之间的数据只是部分完成,必须被视为垃圾数据。 您想要将其删除,并将文件尾随块添加到流。 然后,您应该能够将此编辑的流加载到PictureBox中。

您可以在异步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);

您的解决方案将文件直接读入内存,而我的文件将其保存到磁盘上的文件中,因此该解决方案可能适用于您,也可能不适合您。 如果显示进度指示对您很重要,则此方法可以正常工作,您始终可以下载到临时文件,然后在文件控件完成后将其加载到图像控件中。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM