Wie kann man prüfen, ob System.Net.WebClient.DownloadData ist eine binäre Datei herunterzuladen?

StackOverflow https://stackoverflow.com/questions/153451

  •  03-07-2019
  •  | 
  •  

Frage

Ich versuche WebClient zu verwenden, um eine Datei aus dem Internet zum Herunterladen einer WinForms-Anwendung. Allerdings möchte ich wirklich nur HTML-Datei zum Download bereit. Jede andere Art Ich möchte ignorieren.

Ich habe die WebResponse.ContentType, aber sein Wert ist immer null.

Wer noch keine Ahnung, was die Ursache sein könnte?

War es hilfreich?

Lösung

Da Ihr Update, Sie können dies tun, indem Sie den .Verfahren in GetWebRequest Ändern:

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;
    }
}

Alternativ können Sie den Header überprüfen, wenn GetWebRespons () überschreiben, vielleicht eine Ausnahme werfen, wenn es nicht das, was man will:

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

Andere Tipps

Ich bin die Ursache nicht sicher, aber vielleicht hatte man noch nichts heruntergeladen. Dies ist die faule Art den Inhaltstyp einer Remote-Datei / Seite zu bekommen (ich habe nicht geprüft, ob diese auf dem Draht effizient ist. Soweit ich weiß, kann es große Teile der Inhalte herunterladen)

        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 ist eine abstrakte Klasse und die Contenttype-Eigenschaft wird in Vererbungsklassen definiert. Zum Beispiel in dem HttpWebRequest Objekt wird diese Methode überlastet die Content-Type-Header zur Verfügung zu stellen. Ich bin mir nicht sicher, welche Instanz von WebResponse des WebClient verwendet. Wenn Sie nur HTML-Dateien möchten, Ihre besten direkt die HttpWebRequest-Objekt.

Sie können die erste Anforderung mit dem HEAD Verb ausgeben, und prüfen Sie den Content-Type-Response-Header? [Bearbeiten] Es sieht aus wie Sie HttpWebRequest dafür verwenden müssen, werden, wenn.

Ihre Frage ist ein wenig verwirrend: Wenn Sie eine Instanz der Klasse Net.WebClient verwenden, wird die Net.WebResponse nicht in die Gleichung ein (abgesehen von der Tatsache, dass es in der Tat eine abstrakte Klasse, und Sie‘ seine d eine konkrete Umsetzung wie HttpWebResponse verwenden, wie in einer anderen Antwort darauf hingewiesen).

Wie auch immer, wenn WebClient verwenden, können Sie erreichen, was Sie wollen von so etwas wie dies zu tun:

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

Beachten Sie, dass für die Existenz der Content-Type-Header zu prüfen haben, da der Server nicht garantiert wird zurückzukehren (obwohl die meisten modernen HTTP-Server werden immer es enthalten). Wenn keine Content-Type-Header vorhanden sind, können Sie in einem anderen HTML-Detektionsverfahren, zum Beispiel fallen die Datei zu öffnen, das Lesen die ersten 1K Zeichen oder so in einen String, und zu sehen, ob das den Teil enthält

Beachten Sie auch, dass dies ein wenig verschwenderisch ist, wie Sie immer die vollständige Datei übertragen werden, vor der Entscheidung, ob Sie es wollen oder nicht. Zum Umgehen, dass die Umstellung auf den Net.HttpWebRequest / Response-Klassen helfen können, aber ob der zusätzliche Code ist es wert hängt von Ihrer Anwendung ...

Ich entschuldige mich für nicht sehr klar. Ich schrieb eine Wrapper-Klasse, die WebClient erstreckt. In dieser Wrapper-Klasse, habe ich Cookie Container und ausgesetzt, um die Timeout-Eigenschaft für die WebRequest.

Ich war mit DownloadDataAsync () von dieser Wrapper-Klasse und ich war nicht in der Lage von WebResponse dieser Wrapper-Klasse Content-Typ abzurufen. Mein Hauptziel ist es, die Reaktion abzufangen und bestimmen, ob seine von text / html Natur. Wenn es nicht ist, werde ich diese Anforderung abbrechen.

ich es geschafft, den Content-Type nach zwingenden WebClient.GetWebResponse (WebRequest, IAsyncResult) -Methode zu erhalten.

Hier finden Sie eine Auswahl meiner Wrapper-Klasse:

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;
    }
}

Hier ist ein Verfahren unter Verwendung von TCP, die http oben auf gebaut ist. Es wird zurückkehren, wenn angeschlossen oder nach dem Timeout (Millisekunden), so dass der Wert muss möglicherweise auf Ihrer Situation zu ändern, je

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;
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top