如何在C#中下载zip文件?

18

我使用HTTP GET方法在浏览器中下载一个zip文件,类似于 https://example.com/up/DBID/a/rRID/eFID/vVID(不是确切的url)。

现在,当我尝试在C#代码中执行相同的下载(使用与上述相同的GET方法),下载的zip文件不是有效的存档文件。当我在记事本中打开这个文件时,它是一些HTML页面。

我认为我没有正确设置某些标头。我搜索了一下示例,在上传方面找到了几个示例,但在下载方面没有看到任何东西。

代码:

HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "GET";
request.ContentType = "application/zip";
try
{
    HttpWebResponse res = (HttpWebResponse)request.GetResponse();
    using (StreamReader sr = new StreamReader(res.GetResponseStream(), System.Text.Encoding.Default))
    {
        StreamWriter oWriter = new StreamWriter(@"D:\Downloads\1.zip");
        oWriter.Write(sr.ReadToEnd());
        oWriter.Close();
    }
    res.Close();
}
catch (Exception ex)
{
}

4
这是一个难以猜测的“它不工作”的问题。请发布代码,并记录您在十六进制查看器中打开文件时看到的内容。 - Hans Passant
4个回答

43

主要原因是你使用了 StreamWriter : TextWriter 来处理二进制Zip文件。StreamWriter 期望的是文本并会应用编码。即使是简单的ASCII编码器也可能尝试“修复”它认为无效的行结尾。

你可以用以下代码替换所有代码:

  using (var client = new WebClient())
  {
    client.DownloadFile("http://something",  @"D:\Downloads\1.zip");
  }

注意,对于新的代码,您应该使用HttpClient,而不是WebClient。
然后不要使用using( ) { }


WebClient也创建了相同类型的zip文件。 - Merrin
@Merrin,如果你指的是“相同有问题的Zip文件”,那么你需要提供(更多)详细信息。 - H H
1
我认为我面临的问题是对服务的身份验证。然后我可能可以使用WebClient下载文件。 - Merrin
1
@HenkHolterman哦,我的天啊,这个答案真的为我节省了太多时间。非常感谢您和带我来到这里的Google。 - Mike G
1
@HenkHolterman 谢谢伙计。你救了我的命。它运行得很好 :) - Arul Sidthan
显示剩余9条评论

8

你可以使用WebClient来实现两行代码:

using(WebClient wc = new WebClient())
{
   wc.DownloadFile(url, @"D:\Downloads\1.zip");
}

短小简洁的编程方式我很喜欢。给你点赞! - Al Kepp
2
@anvarbekraupov:我正在使用using语句 - 再仔细看看。 - BrokenGlass
@BrokenGlass,我用+1替换了我的降级,非常抱歉! - Bek Raupov

3
您可以使用System.Net.Http.HttpClient。
using (HttpClient client = new HttpClient())
{
        using (HttpResponseMessage response = await client.GetAsync(downloadURL))
        {
             using(var stream = await response.Content.ReadAsStreamAsync())
             {
                  using(Stream zip = FileManager.OpenWrite(ZIP_PATH))
                  {
                       stream.CopyTo(zip);
                  }
             }
        }
}

1

在 Ruben 的回答基础上进行扩展,可以像这样添加一个扩展方法 HttpClient 而不是 WebClient

using System.IO;
using System.Net.Http;
using System.Threading.Tasks;

public static class Extensions
{
    public static async Task DownloadFile (this HttpClient client, string address, string fileName) {
        using (var response = await client.GetAsync(address))
        using (var stream = await response.Content.ReadAsStreamAsync())
        using (var file = File.OpenWrite(fileName)) {
            stream.CopyTo(file);
        }
    }
}

然后像这样使用:

var archivePath = "https://api.github.com/repos/microsoft/winget-pkgs/zipball/";
using (var httpClient = new HttpClient())
{
    await httpClient.DownloadFile(archivePath, "./repo.zip");
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接