文件未完全下载

时间:2013-04-17 18:04:59

标签: c# .net download httprequest

我正在开发一个从给定网址下载视频的应用程序。问题是我没有收到整个文件内容,然后无法播放该文件。例如,尝试下载大小约为2.23 MB的视频,只给我2.11 MB。当我在浏览器中使用URL时,它会显示一个用于保存视频的对话框,并且文件已成功下载。

我已尝试使用WebClient类,但它可以正常工作,但我想以块的形式下载文件,以便能够报告状态(完成百分比)。这是我使用的代码:

private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
    int bufferSize = 1024 * 300;
    string filePath = saveFileDialog.FileName;
    if (File.Exists(filePath))
        File.Delete(filePath);
    int totalBytes = 0;
    HttpWebRequest webRequest = (HttpWebRequest)HttpWebRequest.Create(DownloadUrl);
    long contentLength = webRequest.GetResponse().ContentLength;
    using (Stream webStream = webRequest.GetResponse().GetResponseStream())
    using (StreamReader reader = new StreamReader(webStream))
    using (BinaryWriter fileWriter = new BinaryWriter(File.Create(filePath)))
    {
        do
        {
            char[] buffer = new char[bufferSize];
            bytesRead = reader.ReadBlock(buffer, 0, bufferSize); // also tried with Read(buffer, 0, bufferSize);
            totalBytes += bytesRead;
            Console.WriteLine("Bytes read: " + bytesRead + " Total Bytes: " + totalBytes + " Content length: " + contentLength);
            if (bytesRead > 0)
                fileWriter.Write(buffer, 0, bytesRead);
        } while (!reader.EndOfStream);
    }
}

我也尝试阅读bytesRead = 0,但结果相同。 有什么东西我不见了吗?

2 个答案:

答案 0 :(得分:1)

我建议您改用DownloadFileAsync。这为您提供了两个事件,可以更轻松地跟踪下载进度。

DownloadProgressChangedEventHandler

DownloadFileCompleted

一个非常简单的实现看起来像这样。

WebClient client = new WebClient();

client.DownloadProgressChanged += 
        new DownloadProgressChangedEventHandler(DownloadProgressCallback);

client.DownloadFileAsync(DownloadUrl, filePath);

然后有一个更新进度条的功能。

private void DownloadProgressCallback(object sender, 
                                      DownloadProgressChangedEventArgs e)
{
     myProgressBar.Value = e.ProgressPercentage;
}

您还可以访问e.BytesReceivede.TotalBytesToReceive等数据。


修改:

我必须做的主要更改是将缓冲区从char[]更改为byte[],然后使用Stream而不是StreamReader。

我们还检查文件的结尾,检查是否有任何字节要写入我们的硬盘。如果没有人可以写,我们知道我们已经完成了。

private static void download()
{
    int bufferSize = 1024 * 300;
    string filePath = "Test.exe";

    if (File.Exists(filePath))
        File.Delete(filePath);
    int totalBytes = 0;
    HttpWebRequest webRequest =
        (HttpWebRequest)
        HttpWebRequest.Create(
            @"http://www.rarlab.com/rar/wrar420.exe");
    long contentLength = webRequest.GetResponse().ContentLength;
    Console.WriteLine(totalBytes);

    using (WebResponse webResponse = webRequest.GetResponse())
    using (Stream reader = webResponse.GetResponseStream())
    using (BinaryWriter fileWriter = new BinaryWriter(File.Create(filePath)))
    {
        int bytesRead = 0;
        byte[] buffer = new byte[bufferSize];
        do
        {
            bytesRead = reader.Read(buffer, 0, buffer.Length);
            totalBytes += bytesRead;
            fileWriter.Write(buffer, 0, bytesRead);
            Console.WriteLine("BytesRead: " + bytesRead + " -- TotalBytes: " + totalBytes);

        } while (bytesRead > 0);
    }
}

答案 1 :(得分:0)

尝试

private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
    int bufferSize = 1024 * 300;
    string filePath = saveFileDialog.FileName;
    if (File.Exists(filePath))
        File.Delete(filePath);
    int totalBytes = 0;
    HttpWebRequest webRequest = (HttpWebRequest)HttpWebRequest.Create(DownloadUrl);
    long contentLength = webRequest.GetResponse().ContentLength;
    using (Stream webStream = webRequest.GetResponse().GetResponseStream())
    using (StreamReader reader = new StreamReader(webStream))
    using (BinaryWriter fileWriter = new BinaryWriter(File.Create(filePath)))
    {
        do
        {
            char[] buffer = new char[bufferSize];
            bytesRead = reader.ReadBlock(buffer, 0, bufferSize); // also tried with Read(buffer, 0, bufferSize);
            totalBytes += bytesRead;
            Console.WriteLine("Bytes read: " + bytesRead + " Total Bytes: " + totalBytes + " Content length: " + contentLength);
            if (bytesRead > 0)
                fileWriter.Write(buffer, 0, bytesRead);
        } while (!reader.EndOfStream);
        fileWriter.flush();
    }
}

嗨,这是我的不好,我刚刚在循环外添加 fileWriter.flush();