使用进度条下载文件

时间:2011-11-08 16:58:31

标签: c# webclient

我想在方法中下载文件,然后使用第一种方法中存储在变量中的一些数据继续使用该文件。 我知道你可以使用DownloadFileAsync,但是我需要继续我在DownloadFileCompleted方法中的工作,并且从那里无法访问变量(除非我声明一些全局变量而是使用它,尽管这不是正确的方法我假设)。

所以我用Google搜索并找到了另一种方法,一点一点地手动下载文件。这对我来说非常完美。虽然我想知道的是,如果我的问题还有其他方法/解决方案更简单吗?

或者,如果你可以玩这些事件并获得更适合我的东西:)

哦,如果你找到一个更好的标题,请改变我的问题,我想不出一个。

1 个答案:

答案 0 :(得分:3)

您必须逐个更新进度条。这段代码可以解决问题。

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

您需要分离一个线程来运行此代码,因为它明显是同步的。

e.g。

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