2012-12-27 35 views
1

我似乎無法找到我的問題的工作答案,我不知道是否有人可以幫助。基本上,我有我的網站的鏈接導致一個zip文件被下載:檢測到PHP鏈接導致在c#中下載文件

http://***.com/download.php?id=1 

如果激活網頁上的這個鏈接就會彈出一個另存爲對話框,讓您保存默認文件名的文件ThisIsMyZipFile.zip

我的問題是,在C#如果我使用new Uri("http://***.com/download.pgp?id=1").IsFilefalse所以我似乎返回不能檢測,這是不執行webclient DownloadString,如果前兩個字節是PK看到一個文件。

此外,即使手動下載爲字符串檢測到PK標題並保存該文件我無法找到我的網站想要使用的默認文件名爲ThisIsMyZipFile.zip在這個例子中,因爲我想使用相同的文件名。

有誰知道解決這兩個問題的好方法嗎?

UPDATE

感謝保羅和他的答案,我創建了下面的函數,它不正是我需要的:

/// <summary> 
/// Returns the responded HTTP headers of the given URL and if the link refers to the file it returns extra information about it. 
/// </summary> 
/// <param name="Url">The address.</param> 
/// <returns> 
/// null if a WebException is thrown 
/// otherwise: 
/// List of headers: 
///  Keep-Alive   - Timeout value (i.e. timeout=2, max=100) 
///  Connection   - The type of connection (i.e. Keep-Alive) 
///  Transfer-Encoding - The type of encoding used for the transfer (i.e. chunked) 
///  Content-Type  - The type of Content that will be transferred (i.e. application/zip) 
///  Date    - The servers date and time 
///  Server    - The server that is handling the request (i.e. Apache) 
///  AbsoluteUri   - The full Uri of the resulting link that will be followed. 
/// The following key will be present if the link refers to a file 
///  Filename   - The filename (not path) of the file that will be downloaded if the link if followed. 
/// </returns> 
public Dictionary<string, string> GetHTTPResponseHeaders(string Url) 
{ 
    WebRequest WebRequestObject = HttpWebRequest.Create(Url); 
    WebResponse ResponseObject = null; 
    try 
    { 
     ResponseObject = WebRequestObject.GetResponse(); 
    } 
    catch(WebException ex) 
    { 
     return null; 
    } 
    // Add the header inforamtion to the resulting list 
    Dictionary<string, string> HeaderList = new Dictionary<string, string>(); 
    foreach (string HeaderKey in ResponseObject.Headers) 
     HeaderList.Add(HeaderKey, ResponseObject.Headers[HeaderKey]); 

    // Add the resolved Uri to the resulting list 
    HeaderList.Add("AbsoluteUri", ResponseObject.ResponseUri.AbsoluteUri); 

    // If this is a zip file then add the download filename specified by the server to the resulting list 
    if (ResponseObject.ContentType.ToLower() == "application/zip") 
    { 
     HeaderList.Add("Filename", ResponseObject.ResponseUri.Segments[ResponseObject.ResponseUri.Segments.Length-1]); 
    } 

    // We are now finished with our response object 
    ResponseObject.Close(); 

    // Return the resulting list 
    return HeaderList; 
} 

+1

MSDN說,ISFILE是,如果它匹配UriSchemeFile唯一的真。見http://bit.ly/TB6HZi和http://bit.ly/W6A2pA – MrSoundless

回答

2

Uri.IsFile執行時的URI靜態檢查即它查看'scheme'部分(包括冒號的第一位)是否爲file:。它不查看通過請求駐留在URI的資源返回的實際內容。 (事實上​​,因爲它根本沒有嘗試聯繫服務器,URI實際上可能指向缺少的資源,但IsFile仍然可以工作。)

如果您希望查看資源的內容是特定類型的,那麼你將必須要麼:

  1. 檢索該資源的HTTP報頭(如果它是一個HTTP或HTTPS資源:即,如果「方案」是httphttps)。
  2. 檢索(至少部分)資源並對其進行檢查。

您目前正在做2,但對於HTTP資源(與HTTP URL),那麼這將是更清潔和更便宜的做1.您可以通過執行HTTP請求HEAD(而不是GET做這做c))。這將返回HTTP頭而不返回資源本身。該代碼看起來是這樣的:

var request = WebRequest.Create("http://somewhere.overtherainbow.com/?a=b"); 
request.Method = "HEAD"; 
WebResponse response = request.GetResponse(); 
//TODO check status code 
string contentType = response.ContentType; 
response.Close(); 

內容類型會給你的文件類型的一些指示,但許多二進制文件將只是返回一個字節流,所以您可能還需要檢索和審查如果你想區分不同的二進制文件類型,資源本身的魔術字節。 (內容類型應該足以讓您區分二進制文件和網頁。)

所以,一個完整的解決方案可能是:

  1. 發送對於資源的GET請求。
  2. 檢查響應狀態以確保沒有錯誤。
  3. 檢查內容類型標題以查看我們是否有二進制字節流。
  4. 從響應流中讀取兩個字節以查看文件是否開始「PK」。
+0

謝謝Paul這正是我所需要的。 :-) – DelboyJay

1

您絕對無法檢測到給定的URL會導致下載文件,而無需實際向該URL發送HTTP請求。

現在來解決第二個問題。您可以發送HTTP請求來下載該文件,然後檢查內容處理標頭將包含文件名:

using (var client = new WebClient()) 
{ 
    using (var stream = client.OpenRead("http://*.com/download.php?id=1")) 
    { 
     var disposition = client.ResponseHeaders["Content-Disposition"]; 
     if (disposition != null) 
     { 
      var cd = new ContentDisposition(disposition); 
      if (!cd.Inline && !string.IsNullOrEmpty(cd.FileName)) 
      { 
       using (var outputStream = File.OpenWrite(cd.FileName)) 
       { 
        stream.CopyTo(outputStream); 
       } 
      } 
     } 
     else 
     { 
      // The web server didn't send a Content-Disposition response header 
      // so we have absolutely no means of determining the filename 
      // you will have to use some default value here if you want to store it 
     } 
    } 
}