2017-06-17 30 views
2

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

所以,我使用WebClient来下载favicon,虽然;它似乎并没有完全下载,因为每次打开文件时它都会出现损坏,并引发错误,指出“文件头不能被读取”。

我已经试过到目前为止以下(我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(或类似的东西),如果它的名称有多个句点?或者如果不是这些时期,为什么我不能读取从DuckDuckGo下载的文件?

+0

_“(。)我猜测,在favicon_url的多个周期负责” _ - 这听起来对我来说是一个非常糟糕的猜测。网址是有效的或不是。如果不是,则会在HTTP请求中发生错误,而不是无效的数据。我认为可能更大的问题是,网站不会将实际的Windows图标文件用于其图标。它们实际上是位图,需要像这样读取。你似乎试图将下载的文件传递给一个'Icon'构造函数,但是我怀疑这个文件实际上是一个有效的.ico文件(尽管网站使你可以使用扩展名)。 –

+0

多期不应该是一个问题。你可以在文本编辑器(如记事本)中打开下载的文件,并确认它是否是保存的二进制文件?可能它是一个保存的HTML错误页面。 – James

+0

'favicon_url.ToString()'返回什么?如果您使用“https:// icons.duckduckgo.com/ip2/www.google.com.ico”进行测试,代码是否正常工作? – mjwills

回答

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

这似乎工作得很好,虽然我一直用作测试(youtube.com)的网站似乎将PNG设置为其“快捷图标”,并将其扩展名重命名为图标。所以我将不得不回到另一个将PNG文件转换为Icon的选项,而不会丢失它的质量。不管怎么说,多谢拉! –