WebClient
を使用して、WinFormsアプリケーションを使用してWebからファイルをダウンロードしようとしています。しかし、私は本当にHTMLファイルをダウンロードしたいだけです。無視したい他のタイプ。
WebResponse.ContentType
、ただしその値は常にnull
です。
誰もが原因が何であるか考えていますか?
更新を前提として、GetWebRequestの.Methodを変更することでこれを行うことができます。
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;
}
}
または、GetWebRespons()をオーバーライドするときにヘッダーを確認することもできます。必要な場合は例外がスローされる可能性があります。
protected override WebResponse GetWebResponse(WebRequest request)
{
WebResponse resp = base.GetWebResponse(request);
string type = resp.Headers["content-type"];
// do something with type
return resp;
}
原因はわかりませんが、まだ何もダウンロードしていない可能性があります。これは、リモートファイル/ページのコンテンツタイプを取得するための遅延方法です(これがネットワーク上で効率的であるかどうかは確認していません。私が知っている限りでは、大量のコンテンツがダウンロードされる可能性があります)。
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();
}
WebResponseは抽象クラスであり、ContentTypeプロパティは継承クラスで定義されます。たとえば、HttpWebRequestオブジェクトでは、このメソッドはオーバーロードされてコンテンツタイプヘッダーを提供します。 WebClientが使用しているWebResponseのインスタンスがわかりません。 HTMLファイルのみが必要な場合は、HttpWebRequestオブジェクトを直接使用することをお勧めします。
以下は、HTTPがその上に構築されているTCPを使用する方法です。接続時またはタイムアウト(ミリ秒)後に戻るため、状況に応じて値を変更する必要がある場合があります
var result = false;
try {
using (var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)) {
var asyncResult = socket.BeginConnect(yourUri.AbsoluteUri, 80, null, null);
result = asyncResult.AsyncWaitHandle.WaitOne(100, true);
socket.Close();
}
}
catch { }
return result;
あなたの質問は少し混乱します:Net.WebClientクラスのインスタンスを使用している場合、Net.WebResponseは方程式に入りません(それが実際に抽象クラスであるという事実を除けば、別の応答で指摘されているように、HttpWebResponseなどの具体的な実装)。
とにかく、WebClientを使用している場合、次のようなことを行うことで必要なことを実現できます。
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
サーバーはそれを返すことが保証されていないため、Content-Typeヘッダーの存在を確認する必要があることに注意してください(ほとんどの最新のHTTPサーバーには常に含まれています)。 Content-Typeヘッダーが存在しない場合は、別のHTML検出方法にフォールバックできます。たとえば、ファイルを開いて、最初の1K文字程度を文字列に読み取り、サブ文字列<html>が含まれているかどうかを確認します。
また、必要かどうかを判断する前に、常にファイル全体を転送するため、これは少しもったいないことにも注意してください。これを回避するには、Net.HttpWebRequest/Responseクラスへの切り替えが役立つ場合がありますが、追加のコードが価値があるかどうかは、アプリケーションによって異なります...
HEAD動詞)を使用して最初のリクエストを発行し、コンテンツタイプの応答ヘッダーを確認できますか?[編集]ただし、これにはHttpWebRequestを使用する必要があるようです。
よくわからなかったことをお詫びします。 WebClientを拡張するラッパークラスを作成しました。このラッパークラスでは、Cookieコンテナーを追加し、WebRequestのタイムアウトプロパティを公開しました。
このラッパークラスからDownloadDataAsync()を使用していて、このラッパークラスのWebResponseからコンテンツタイプを取得できませんでした。私の主な目的は、応答を傍受し、text/htmlの性質であるかどうかを判断することです。そうでない場合は、この要求を中止します。
WebClient.GetWebResponse(WebRequest、IAsyncResult)メソッドをオーバーライドした後、なんとかコンテンツタイプを取得できました。
以下は私のラッパークラスのサンプルです。
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;
}
}