2008-09-30 30 views
21

Tôi đang cố gắng sử dụng WebClient để tải xuống tệp từ web bằng ứng dụng WinForms. Tuy nhiên, tôi thực sự chỉ muốn tải xuống tệp HTML. Bất kỳ loại nào khác tôi sẽ muốn bỏ qua.Làm cách nào để kiểm tra xem System.Net.WebClient.DownloadData có tải xuống tệp nhị phân không?

Tôi đã kiểm tra WebResponse.ContentType, nhưng giá trị của nó luôn là null.

Bất kỳ ai có bất kỳ ý tưởng nào có thể là nguyên nhân?

+0

bạn muốn hình ảnh, tờ định kiểu và JavaScript? –

Trả lời

53

Với bản cập nhật, bạn có thể làm điều này bằng cách thay đổi.Phương pháp trong GetWebRequest:

using System; 
using System.Net; 
static class Program 
{ 
    static void Main() 
    { 
     using (MyClient client = new MyClient()) 
     { 
      client.HeadOnly = true; 
      string uri = "http://www.google.com"; 
      byte[] body = client.DownloadData(uri); // note should be 0-length 
      string type = client.ResponseHeaders["content-type"]; 
      client.HeadOnly = false; 
      // check 'tis not binary... we'll use text/, but could 
      // check for text/html 
      if (type.StartsWith(@"text/")) 
      { 
       string text = client.DownloadString(uri); 
       Console.WriteLine(text); 
      } 
     } 
    } 

} 

class MyClient : WebClient 
{ 
    public bool HeadOnly { get; set; } 
    protected override WebRequest GetWebRequest(Uri address) 
    { 
     WebRequest req = base.GetWebRequest(address); 
     if (HeadOnly && req.Method == "GET") 
     { 
      req.Method = "HEAD"; 
     } 
     return req; 
    } 
} 

Ngoài ra, bạn có thể kiểm tra các tiêu đề khi trọng GetWebRespons(), có lẽ ném một ngoại lệ nếu nó không phải là những gì bạn muốn:

protected override WebResponse GetWebResponse(WebRequest request) 
{ 
    WebResponse resp = base.GetWebResponse(request); 
    string type = resp.Headers["content-type"]; 
    // do something with type 
    return resp; 
} 
+2

Đừng quên XHTML: http://www.w3.org/TR/xhtml-media-types/#application-xhtml-xml – bzlm

0

Bạn có thể đưa ra yêu cầu đầu tiên với động từ HEAD và kiểm tra tiêu đề phản hồi kiểu nội dung? [sửa] Có vẻ như bạn sẽ phải sử dụng HttpWebRequest cho điều này, mặc dù.

+0

(lỗi thời theo dõi của OP - xem trả lời khác của tôi về GetWebRequest) –

1

WebResponse là một lớp trừu tượng và thuộc tính ContentType được định nghĩa trong các lớp kế thừa. Ví dụ trong đối tượng HttpWebRequest phương thức này được nạp chồng để cung cấp tiêu đề kiểu nội dung. Tôi không chắc chắn về cá thể của WebResponse mà WebClient đang sử dụng. Nếu bạn CHỈ muốn các tập tin HTML, tốt nhất của bạn bằng cách sử dụng các đối tượng HttpWebRequest trực tiếp.

0

Câu hỏi của bạn hơi khó hiểu: nếu bạn đang sử dụng một thể hiện của lớp Net.WebClient, Net.WebResponse không nhập vào phương trình (ngoài thực tế là nó thực sự là lớp trừu tượng và bạn đang sử dụng triển khai cụ thể như HttpWebResponse, như được chỉ ra trong một phản hồi khác).

Dù sao, khi sử dụng WebClient, bạn có thể đạt được những gì bạn muốn bằng cách làm một cái gì đó như thế này:

Dim wc As New Net.WebClient() 
Dim LocalFile As String = IO.Path.Combine(Environment.GetEnvironmentVariable("TEMP"), Guid.NewGuid.ToString) 
wc.DownloadFile("http://example.com/somefile", LocalFile) 
If Not wc.ResponseHeaders("Content-Type") Is Nothing AndAlso wc.ResponseHeaders("Content-Type") <> "text/html" Then 
    IO.File.Delete(LocalFile) 
Else 
    '//Process the file 
End If 

Lưu ý rằng bạn phải kiểm tra sự tồn tại của header Content-Type, như máy chủ là không được bảo đảm trả lại (mặc dù hầu hết các máy chủ HTTP hiện đại sẽ luôn bao gồm nó). Nếu không có tiêu đề Loại nội dung, bạn có thể quay lại phương thức phát hiện HTML khác, ví dụ: mở tệp, đọc các ký tự 1K đầu tiên hoặc thành chuỗi và xem chuỗi có chứa chuỗi con <html>

Cũng lưu ý rằng đây là một chút lãng phí, vì bạn sẽ luôn luôn chuyển toàn bộ tập tin, trước khi quyết định xem bạn có muốn hay không. Để giải quyết vấn đề đó, việc chuyển sang lớp Net.HttpWebRequest/Response có thể giúp ích, nhưng liệu mã phụ có đáng giá hay không tùy thuộc vào ứng dụng của bạn ...

0

Tôi xin lỗi vì đã không rõ ràng lắm. Tôi đã viết một lớp bao bọc mở rộng WebClient. Trong lớp wrapper này, tôi đã thêm vào thùng chứa cookie và tiếp xúc với thuộc tính timeout cho WebRequest.

Tôi đã sử dụng DownloadDataAsync() từ lớp trình bao bọc này và tôi không thể truy xuất loại nội dung từ WebResponse của lớp trình bao bọc này. Mục đích chính của tôi là đánh chặn phản hồi và xác định xem tính chất văn bản/html của nó. Nếu không, tôi sẽ hủy yêu cầu này.

Tôi đã quản lý để có được loại nội dung sau khi ghi đè phương pháp WebClient.GetWebResponse (WebRequest, IAsyncResult).

Sau đây là một mẫu của lớp wrapper của tôi:

public class MyWebClient : WebClient 
{ 
    private CookieContainer _cookieContainer; 
    private string _userAgent; 
    private int _timeout; 
    private WebReponse _response; 

    public MyWebClient() 
    { 
     this._cookieContainer = new CookieContainer(); 
     this.SetTimeout(60 * 1000); 
    } 

    public MyWebClient SetTimeout(int timeout) 
    { 
     this.Timeout = timeout; 
     return this; 
    } 

    public WebResponse Response 
    { 
     get { return this._response; } 
    } 

    protected override WebRequest GetWebRequest(Uri address) 
    { 
     WebRequest request = base.GetWebRequest(address); 

     if (request.GetType() == typeof(HttpWebRequest)) 
     { 
      ((HttpWebRequest)request).CookieContainer = this._cookieContainer; 
      ((HttpWebRequest)request).UserAgent = this._userAgent; 
      ((HttpWebRequest)request).Timeout = this._timeout; 
     } 

     this._request = request; 
     return request; 
    } 

    protected override WebResponse GetWebResponse(WebRequest request) 
    { 
     this._response = base.GetWebResponse(request); 
     return this._response; 
    } 

    protected override WebResponse GetWebResponse(WebRequest request, IAsyncResult result) 
    { 
     this._response = base.GetWebResponse(request, result); 
     return this._response; 
    } 

    public MyWebClient ServerCertValidation(bool validate) 
    { 
     if (!validate) ServicePointManager.ServerCertificateValidationCallback += delegate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { return true; }; 
     return this; 
    } 
} 
+0

Trong trường hợp đó, hãy thay đổi .Method - xem trả lời khác của tôi. –

3

Tôi không chắc chắn nguyên nhân, nhưng có lẽ bạn chưa tải xuống bất kỳ thứ gì. Đây là cách lười biếng để có được loại nội dung của một tập tin/trang từ xa (Tôi chưa kiểm tra xem điều này có hiệu quả trên dây hay không. Đối với tất cả những gì tôi biết, nó có thể tải xuống một lượng lớn nội dung)

 Stream connection = new MemoryStream(""); // Just a placeholder 
     WebClient wc = new WebClient(); 
     string contentType; 
     try 
     { 
      connection = wc.OpenRead(current.Url); 
      contentType = wc.ResponseHeaders["content-type"]; 
     } 
     catch (Exception) 
     { 
      // 404 or what have you 
     } 
     finally 
     { 
      connection.Close(); 
     } 
Các vấn đề liên quan