2017-06-17 93 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的選項,而不會丟失它的質量。不管怎麼說,多謝拉! –