在 C# 中使用 WebClient 有没有办法在重定向后获取站点的 URL?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/690587/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 13:38:32  来源:igfitidea点击:

Using WebClient in C# is there a way to get the URL of a site after being redirected?

c#.netregexhttp

提问by Matthew Rathbone

Using the WebClient class I can get the title of a website easily enough:

使用 WebClient 类,我可以很容易地获得网站的标题:

WebClient x = new WebClient();    
string source = x.DownloadString(s);
string title = Regex.Match(source, 
    @"\<title\b[^>]*\>\s*(?<Title>[\s\S]*?)\</title\>",
    RegexOptions.IgnoreCase).Groups["Title"].Value;

I want to store the URL and the page title. However when following a link such as:

我想存储 URL 和页面标题。但是,当点击以下链接时:

http://tinyurl.com/dbysxp

http://tinyurl.com/dbysxp

I'm clearly going to want to get the Url I'm redirected to.

我显然想要获得我被重定向到的 URL。

QUESTIONS

问题

Is there a way to do this using the WebClientclass?

有没有办法使用这个WebClient类来做到这一点?

How would I do it using HttpResponseand HttpRequest?

我将如何使用HttpResponseand做到这一点HttpRequest

采纳答案by Will Dean

If I understand the question, it's much easier than people are saying - if you want to let WebClient do all the nuts and bolts of the request (including the redirection), but then get the actualresponse URI at the end, you can subclass WebClient like this:

如果我理解这个问题,它比人们说的要容易得多 - 如果您想让 WebClient 完成请求的所有细节(包括重定向),然后在最后获得实际的响应 URI,您可以将 WebClient 子类化像这样:

class MyWebClient : WebClient
{
    Uri _responseUri;

    public Uri ResponseUri
    {
        get { return _responseUri; }
    }

    protected override WebResponse GetWebResponse(WebRequest request)
    {
        WebResponse response = base.GetWebResponse(request);
        _responseUri = response.ResponseUri;
        return response;
    }
}

Just use MyWebClient everywhere you would have used WebClient. After you've made whatever WebClient call you needed to do, then you can just use ResponseUri to get the actual redirected URI. You'd need to add a similar override for GetWebResponse(WebRequest request, IAsyncResult result) too, if you were using the async stuff.

只需在您会使用 WebClient 的任何地方使用 MyWebClient。在您完成您需要执行的任何 WebClient 调用之后,您就可以使用 ResponseUri 来获取实际的重定向 URI。 如果您使用的是异步内容,您还需要为 GetWebResponse(WebRequest request, IAsyncResult result) 添加类似的覆盖。

回答by casperOne

With an HttpWebRequest, you would set the AllowAutoRedirectpropertyto false. When this happens, any response with a status code between 300-399 will not be automatically redirected.

使用HttpWebRequest,您可以将该AllowAutoRedirect属性设置为false。发生这种情况时,任何状态代码在 300-399 之间的响应都不会自动重定向。

You can then get the new url from the response headers and then create a new HttpWebRequestinstance to the new url.

然后,您可以从响应标头中获取新 url,然后为新 url 创建一个新HttpWebRequest实例。

With the WebClientclass, I doubt you can change it out-of-the-box so that it does not allow redirects. What you could do is derive a class from the WebClientclass and then override the GetWebRequestand the GetWebResponsemethods to alter the WebRequest/WebResponseinstances that the base implementation returns; if it is an HttpWebRequest, then set the AllowAutoRedirectproperty to false. On the response, if the status code is in the range of 300-399, then issue a new request.

对于WebClientclass,我怀疑您是否可以开箱即用地更改它,以便它不允许重定向。您可以做的是从WebClient该类派生一个类,然后覆盖GetWebRequestGetWebResponse方法以更改基本实现返回的WebRequest/WebResponse实例;如果是HttpWebRequest,则将该AllowAutoRedirect属性设置为false。在响应中,如果状态码在 300-399 范围内,则发出新请求。

However, I don't know that you can issue a new request from within the GetWebRequest/GetWebResponsemethods, so it might be better to just have a loop that executes with HttpWebRequest/HttpWebResponseuntil all the redirects are followed.

但是,我不知道您可以从GetWebRequest/GetWebResponse方法中发出新请求,因此最好只使用HttpWebRequest/执行循环,HttpWebResponse直到遵循所有重定向。

回答by Albert

The WebClient class has an option to follow redirects. Set that option and you should be fine.

WebClient 类具有跟踪重定向的选项。设置该选项,你应该没问题。

回答by Shea

HttpWebRequest.AllowAutoRedirect can be set to false. Then you'd have to manually http status codes in the 300 range.

HttpWebRequest.AllowAutoRedirect 可以设置为 false。然后您必须手动设置 300 范围内的 http 状态代码。

// Create a new HttpWebRequest Object to the mentioned URL.
HttpWebRequest myHttpWebRequest=(HttpWebRequest)WebRequest.Create("http://www.contoso.com");    
myHttpWebRequest.MaximumAutomaticRedirections=1;
myHttpWebRequest.AllowAutoRedirect=true;
HttpWebResponse myHttpWebResponse=(HttpWebResponse)myHttpWebRequest.GetResponse();  

回答by danswain

Ok this is really hackish, but the key is to use the HttpWebRequest and then set the AllowAutoRedirect property to true.

好的,这真的很黑,但关键是使用 HttpWebRequest,然后将 AllowAutoRedirect 属性设置为 true。

Here's a VERY hacked together example

这是一个非常黑客化的例子

        HttpWebRequest req = (HttpWebRequest)WebRequest.Create("http://tinyurl.com/dbysxp");
        req.Method = "GET";
        req.AllowAutoRedirect = true;
        WebResponse response = req.GetResponse();

        response.GetResponseStream();
        Stream responseStream = response.GetResponseStream();

        // Content-Length header is not trustable, but makes a good hint.
        // Responses longer than int size will throw an exception here!
        int length = (int)response.ContentLength;

        const int bufSizeMax = 65536; // max read buffer size conserves memory
        const int bufSizeMin = 8192;  // min size prevents numerous small reads

        // Use Content-Length if between bufSizeMax and bufSizeMin
        int bufSize = bufSizeMin;
        if (length > bufSize)
            bufSize = length > bufSizeMax ? bufSizeMax : length;

        StringBuilder sb;
        // Allocate buffer and StringBuilder for reading response
        byte[] buf = new byte[bufSize];
        sb = new StringBuilder(bufSize);

        // Read response stream until end
        while ((length = responseStream.Read(buf, 0, buf.Length)) != 0)
            sb.Append(Encoding.UTF8.GetString(buf, 0, length));

        string source = sb.ToString();string title = Regex.Match(source, 
        @"\<title\b[^>]*\>\s*(?<Title>[\s\S]*?)\</title\>",RegexOptions.IgnoreCase).Groups["Title"].Value;

enter code here

enter code here

回答by WhySoSerious

I know this is already an answered question, but this works pretty to me:

我知道这已经是一个已回答的问题,但这对我来说很有效:

 HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://tinyurl.com/dbysxp");
 request.AllowAutoRedirect = false;
 HttpWebResponse response = (HttpWebResponse)request.GetResponse();
 string redirUrl = response.Headers["Location"];
 response.Close();

 //Show the redirected url
 MessageBox.Show("You're being redirected to: "+redirUrl);

Cheers.! ;)

干杯。!;)

回答by Stephan Unrau

I got the Uri for the redirected page and the page contents.

我得到了重定向页面和页面内容的 Uri。

HttpWebRequest request = (HttpWebRequest)WebRequest.Create(strUrl);
request.AllowAutoRedirect = true;

HttpWebResponse response = (HttpWebResponse)request.GetResponse();
Stream dataStream = response.GetResponseStream();

strLastRedirect = response.ResponseUri.ToString();

StreamReader reader = new StreamReader(dataStream);              
string strResponse = reader.ReadToEnd();

response.Close();

回答by JimiLoe

In case you are only interested in the redirect URI you can use this code:

如果您只对重定向 URI 感兴趣,您可以使用以下代码:

public static string GetRedirectUrl(string url)
{
     HttpWebRequest request = (HttpWebRequest) HttpWebRequest.Create(url);
     request.AllowAutoRedirect = false;

     using (HttpWebResponse response = HttpWebResponse)request.GetResponse())
     {
         return response.Headers["Location"];
     }
}

The method will return

该方法将返回

  • null - in case of no redirect
  • a relative url - in case of a redirect
  • null - 在没有重定向的情况下
  • 相对 url - 在重定向的情况下

Please note: The usingstatement (or a final response.close()) is essential. See MSDN Libraryfor details. Otherwise you may run out of connections or get a timeout when executing this code multiple times.

请注意using声明(或最终response.close())是必不可少的。有关详细信息,请参阅MSDN 库。否则,在多次执行此代码时,您可能会耗尽连接或超时。