【问题标题】:Downloading an .ico file from DuckDuckGo从 DuckDuckGo 下载 .ico 文件
【发布时间】:2017-06-17 06:17:18
【问题描述】:

我目前正在使用 DuckDuckGo 图标实用程序来获取某些网页的图标,但为了获取图标,它需要您在请求的最后添加“.ico”,例如:https://icons.duckduckgo.com/ip2/www.google.com.ico

所以,我使用WebClient 来下载网站图标,不过;它似乎没有完全下载它,因为每次我打开文件时它都会出现损坏并抛出一个错误,指出“文件头无法读取”。

到目前为止,我已经尝试过以下方法(我的WebClient 称为client,要设置的图标称为favicon,图标文件的路径称为favicon_path):

Uri favicon_url = new Uri(
    "https://icons.duckduckgo.com/ip2/" + gBrowser.Url.Host.ToString() + ".ico");
client.DownloadFile(@favicon_url, favicon_path);
favicon = new Icon(favicon_path);

Uri favicon_url = new Uri("https://icons.duckduckgo.com/ip2/"
    + gBrowser.Url.Host.ToString().Replace(".", "%2E") + ".ico");
client.DownloadFile(@favicon_url, favicon_path);
favicon = new Icon(favicon_path);

我猜 favicon_url 中的多个句点 ('.') 是负责任的,所以我的问题是:如何使用 WebClient(或类似的东西)下载 favicon如果它的名称中有多个句点?或者如果不是句号,为什么我不能读取从 DuckDuckGo 下载的文件?

【问题讨论】:

  • “我猜测 favicon_url 中的多个句点 (.) 是有原因的” ——这听起来对我来说是一个非常糟糕的猜测。 URL 有效或无效。如果不是,您将在 HTTP 请求上收到错误,而不是无效数据。我认为更大的问题可能是网站不使用实际的 Windows 图标文件作为其图标。它们实际上是位图,需要按原样读取。您似乎正在尝试将下载的文件传递给 Icon 构造函数,但我怀疑该文件实际上是一个有效的 .ico 文件(尽管网站让您使用扩展名)。
  • 多个句点应该不是问题。能否在记事本等文本编辑器中打开下载的文件,确认是否是正在保存的二进制文件?可能是正在保存的 HTML 错误页面。
  • favicon_url.ToString() 返回什么?如果您使用https://icons.duckduckgo.com/ip2/www.google.com.ico 进行测试,代码是否有效?
  • 好吧,我对它是否是有效的 .ico 文件的问题进行了纠正(通过我自己对数据的检查)。这是。但我仍然认为下载问题与时期无关。您正在以其他方式破坏数据。
  • "gBrowser" 是一个 Web 浏览器控件,因此它只是获取 Web 浏览器控件中加载的 URL 的主机。 “icons.duckduckgo.com/ip2”总是返回一个图标文件,它在获取网站的图标(包括在必要时将其转换为图标)方面完成所有繁重的工作。 @mjwills 即使使用建议的 URL 进行测试,代码也不起作用。

标签: c# .net winforms


【解决方案1】:

好的,这是你需要做的(在致电DownloadFile() 之后):

using (Stream inputStream = File.OpenRead(favicon_path))
using (Stream gzipStream = new GZipStream(inputStream, CompressionMode.Decompress))
{
    MemoryStream copyStream = new MemoryStream();

    gzipStream.CopyTo(copyStream);
    copyStream.Position = 0;

    favicon = new Icon(copyStream);
}

我注意到下载的文件比实际的 .ico 文件小得多。这表明数据正在以某种方式被压缩。 Gzip 是事实上的跨平台流压缩格式,所以我猜测并尝试将数据解压缩,就好像它是用 gzip 压缩的一样。果然,确实如此。

请注意,您需要先将数据解压缩到中间缓冲区中(我使用了MemoryStream 对象)。 Icon 构造函数将尝试寻找流,GzipStream 对象不支持该流(原因很明显)。因此,您需要将数据解压缩为一个 可搜索的Stream 对象。

另请注意,还有一个使用HttpWebRequest 的替代解决方案,确实支持下载期间的解压缩。这是而不是使用WebClient.DownloadFile(),而不是在上面的另一个示例之后。

您仍然必须先复制到中间缓冲区(同样,因为Icon 想要寻找不可寻找的源流)。但是这种方法允许将数据直接从远程服务器读取到Icon 对象中,而不需要中间文件:

HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(favicon_url);

// You can also include `DecompressionMethods.Deflate` here, for a more general solution
request.AutomaticDecompression = DecompressionMethods.GZip;

MemoryStream copyStream = new MemoryStream();

request.GetResponse().GetResponseStream().CopyTo(copyStream);
copyStream.Position = 0;
favicon = new Icon(copyStream);

【讨论】:

  • 这似乎工作得很好,尽管我一直用作测试的网站 (youtube.com) 似乎将 PNG 设置为他们的“快捷方式图标”,扩展名重命名为好像这是一个图标。所以我将不得不回到我的另一个选项,将 PNG 文件转换为图标而不损失其质量。无论如何,谢谢!
猜你喜欢
  • 2017-05-13
  • 1970-01-01
  • 1970-01-01
  • 2013-09-02
  • 2021-01-04
  • 1970-01-01
  • 2012-08-24
  • 2011-07-11
相关资源
最近更新 更多