C# 如何检查System.Net.WebClient.DownloadData是否正在下载二进制文件?
我正在尝试使用C# 如何检查System.Net.WebClient.DownloadData是否正在下载二进制文件?,c#,file,download,webclient,C#,File,Download,Webclient,我正在尝试使用WebClient使用WinForms应用程序从web下载文件。然而,我真的只想下载HTML文件。我想忽略的任何其他类型 我检查了WebResponse.ContentType,但它的值总是null 有人知道原因是什么吗?您可以使用HEAD动词发出第一个请求,并检查content-type响应头?[编辑]看起来您必须为此使用HttpWebRequest。WebResponse是一个抽象类,ContentType属性是在继承类中定义的。例如,在HttpWebRequest对象中,重载
WebClient
使用WinForms应用程序从web下载文件。然而,我真的只想下载HTML文件。我想忽略的任何其他类型
我检查了WebResponse.ContentType
,但它的值总是null
有人知道原因是什么吗?您可以使用HEAD动词发出第一个请求,并检查content-type响应头?[编辑]看起来您必须为此使用HttpWebRequest。WebResponse是一个抽象类,ContentType属性是在继承类中定义的。例如,在HttpWebRequest对象中,重载此方法以提供内容类型头。我不确定WebClient正在使用哪个WebResponse实例。如果您只需要HTML文件,那么最好直接使用HttpWebRequest对象。您的问题有点让人困惑:如果您使用的是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
Dim wc As New Net.WebClient()
Dim LocalFile为String=IO.Path.Combine(Environment.GetEnvironmentVariable(“TEMP”)、Guid.NewGuid.ToString)
wc.DownloadFile(“http://example.com/somefile,本地文件)
如果wc.ResponseHeaders(“内容类型”)不是空的,那么wc.ResponseHeaders(“内容类型”)“text/html”也是空的
IO.File.Delete(LocalFile)
其他的
“//处理该文件
如果结束
请注意,您必须检查Content-Type头的存在,因为服务器不能保证返回它(尽管大多数现代HTTP服务器总是包含它)。如果不存在内容类型标头,则可以使用另一种HTML检测方法,例如打开文件,将前1K个左右的字符读入字符串,然后查看该字符串是否包含子字符串
还要注意的是,这有点浪费,因为在决定是否需要之前,您总是要传输完整的文件。要解决这个问题,切换到Net.HttpWebRequest/Response类可能会有所帮助,但额外的代码是否值得,取决于您的应用程序…很抱歉,我不是很清楚。我编写了一个包装cla在这个包装类中,我添加了cookie容器,并公开了WebRequest的timeout属性 我正在使用此包装类中的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;
}
}
根据您的更新,您可以通过更改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;
}
}
或者,您可以在重写GetWebResponse()时检查标头,如果它不是您想要的,则可能会引发异常:
protected override WebResponse GetWebResponse(WebRequest request)
{
WebResponse resp = base.GetWebResponse(request);
string type = resp.Headers["content-type"];
// do something with type
return resp;
}
我不确定原因,但可能您还没有下载任何内容。这是一种获取远程文件/页面内容类型的惰性方法(我还没有检查这在网络上是否有效。据我所知,它可能会下载大量内容)
下面是一个使用TCP的方法,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;
您想要图像、样式表和JavaScript吗?在这种情况下,更改.Method-请参阅我的另一个答复。(被OP的后续行动淘汰-请参阅我关于GetWebRequest的另一个答复)别忘了XHTML:
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;