C#中使用 HttpWebRequest 向网站提交数据

HttpWebRequest 是 .NET 基类库中的一个类,在命名空间 System.Net 里,用来使用户通过 HTTP 协议和服务器交互。 

HttpWebRequest 对 HTTP 协议进行了完整的封装,对 HTTP 协议中的 Header, Content, Cookie 都做了属性和方法的支持,很容易就能编写出一个模拟浏览器自动登录的程序。 

 

下面是HttpWebRequest的一些属性,这些属性对于轻量级的自动化测试程序是非常重要的。

AllowAutoRedirect:获取或设置一个值,该值指示请求是否应跟随重定向响应。

CookieContainer:获取或设置与此请求关联的cookie。

Credentials:获取或设置请求的身份验证信息。

KeepAlive:获取或设置一个值,该值指示是否与 Internet 资源建立持久性连接。

MaximumAutomaticRedirections:获取或设置请求将跟随的重定向的最大数目。

Proxy:获取或设置请求的代理信息。

SendChunked:获取或设置一个值,该值指示是否将数据分段发送到 Internet 资源。

Timeout:获取或设置请求的超时值。

UserAgent:获取或设置 User-agent HTTP 标头的值


程序使用 HTTP 协议和服务器交互主要是进行数据的提交,通常数据的提交是通过 GET 和 POST 两种方式来完成,下面对这两种方式进行一下说明: 

1. GET 方式。 

GET 方式通过在网络地址附加参数来完成数据的提交,比如在地址 http://www.google.com/webhp?hl=zh-CN 中,前面部分 http://www.google.com/webhp 表示数据提交的网址,后面部分 hl=zh-CN 表示附加的参数,其中 hl 表示一个键(key), zh-CN 表示这个键对应的值(value)。程序代码如下: 

HttpWebRequest req = (HttpWebRequest) HttpWebRequest.Create( "http://www.google.com/webhp?hl=zh-CN" );
req.Method = "GET";
using (WebResponse wr = req.GetResponse())
{
   //在这里对接收到的页面内容进行处理
} 


2. POST 方式。

 POST 方式通过在页面内容中填写参数的方法来完成数据的提交,参数的格式和 GET 方式一样,是类似于 hl=zh-CN&newwindow=1 这样的结构。程序代码如下: 

string param = "hl=zh-CN&newwindow=1";
byte[] bs = Encoding.ASCII.GetBytes(param);

HttpWebRequest req = (HttpWebRequest) HttpWebRequest.Create( "http://www.google.com/intl/zh-CN/" );
req.Method = "POST";
req.ContentType = "application/x-www-form-urlencoded";
req.ContentLength = bs.Length;

using (Stream reqStream = req.GetRequestStream())
{
   reqStream.Write(bs, 0, bs.Length);
}
using (WebResponse wr = req.GetResponse())
{
   //在这里对接收到的页面内容进行处理
} 

在上面的代码中,我们访问了 www.google.com 的网址,分别以 GET 和 POST 方式提交了数据,并接收了返回的页面内容。然而,如果提交的参数中含有中文,那么这样的处理是不够的,需要对其进行编码,让对方网站能够识别。 


3. 使用 GET 方式提交中文数据。 

GET 方式通过在网络地址中附加参数来完成数据提交,对于中文的编码,常用的有 gb2312 和 utf8 两种,用 gb2312 方式编码访问的程序代码如下: 

Encoding myEncoding = Encoding.GetEncoding("gb2312");
string address = "http://www.baidu.com/s?" + HttpUtility.UrlEncode("参数一", myEncoding) + "=" + HttpUtility.UrlEncode("值一", myEncoding);
HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(address);
req.Method = "GET";
using (WebResponse wr = req.GetResponse())
{
   //在这里对接收到的页面内容进行处理
} 

在上面的程序代码中,我们以 GET 方式访问了网址 http://www.baidu.com/s ,传递了参数“参数一=值一”,由于无法告知对方提交数据的编码类型,所以编码方式要以对方的网站为标准。常见的网站中, www.baidu.com (百度)的编码方式是 gb2312, www.google.com (谷歌)的编码方式是 utf8。 

4. 使用 POST 方式提交中文数据。 

POST 方式通过在页面内容中填写参数的方法来完成数据的提交,由于提交的参数中可以说明使用的编码方式,所以理论上能获得更大的兼容性。用 gb2312 方式编码访问的程序代码如下: 

Encoding myEncoding = Encoding.GetEncoding("gb2312");
string param = HttpUtility.UrlEncode("参数一", myEncoding) + "=" + HttpUtility.UrlEncode("值一", myEncoding) + "&" + HttpUtility.UrlEncode("参数二", myEncoding) + "=" + HttpUtility.UrlEncode("值二", myEncoding);

byte[] postBytes = Encoding.ASCII.GetBytes(param);

HttpWebRequest req = (HttpWebRequest) HttpWebRequest.Create( "http://www.baidu.com/s" );
req.Method = "POST";
req.ContentType = "application/x-www-form-urlencoded;charset=gb2312";
req.ContentLength = postBytes.Length;

using (Stream reqStream = req.GetRequestStream())
{
   reqStream.Write(bs, 0, bs.Length);
}
using (WebResponse wr = req.GetResponse())
{
   //在这里对接收到的页面内容进行处理
} 

从上面的代码可以看出, POST 中文数据的时候,先使用 UrlEncode 方法将中文字符转换为编码后的 ASCII 码,然后提交到服务器,提交的时候可以说明编码的方式,用来使对方服务器能够正确的解析。 


以上列出了客户端程序使用 HTTP 协议与服务器交互的情况,常用的是 GET 和 POST 方式。WebService 也是通过 HTTP 协议来交互的,使用的是 POST 方法。与以上稍有所不同的是, WebService 提交的数据内容和接收到的数据内容都是使用了 XML 方式编码。所以, HttpWebRequest 也可以使用在调用 WebService 的情况下。

 

C#中使用 HttpWebRequest 向网站提交数据的实例代码:

using System;
using System.IO;
using System.Net;
using System.Xml;

namespace Better517Na.HttpHelper
{
    /// <summary>
    /// WebCommon类 
    /// </summary>
    public class WebCommon
    {
        /// <summary>
        /// 获取请求结果
        /// </summary>
        /// <param name="requestUrl">请求地址</param>
        /// <param name="refere">请求源</param>
        /// <param name="timeout">超时时间(秒)</param>
        /// <param name="isPost">是否post提交</param>
        /// <param name="msg">抛出的错误信息</param>
        /// <param name="parameters">参数列表</param>
        /// <returns>返回请求结果</returns>
        public static string HttpWebRequest(string requestUrl, string refere, int timeout, bool isPost, out string msg, params string[] parameters)
        {
            return HttpWebRequest(requestUrl, refere, timeout, isPost, "utf-8", out msg, parameters);
        }

        /// <summary>
        /// 获取请求结果
        /// </summary>
        /// <param name="requestUrl">请求地址</param>
        /// <param name="refere">请求源</param>
        /// <param name="timeout">超时时间(秒)</param>
        /// <param name="isPost">是否post提交</param>
        /// <param name="encoding">编码格式 例如:utf-8</param>
        /// <param name="msg">抛出的错误信息</param>
        /// <param name="parameters">参数列表</param>
        /// <returns>返回请求结果</returns>
        public static string HttpWebRequest(string requestUrl, string refere, int timeout, bool isPost, string encoding, out string msg, params string[] parameters)
        {
            msg = string.Empty;
            string result = string.Empty;
            string ps = string.Empty;
            try
            {
                // 构造入参
                if (parameters != null && parameters.Length >= 1)
                {
                    ps = string.Join("&", parameters);
                }

                // 构造url
                string urlPath = string.Empty;
                if (isPost)
                {
                    urlPath = requestUrl;
                }
                else
                {
                    if (requestUrl.IndexOf("?") < 0)
                    {
                        urlPath = string.Format("{0}?{1}", requestUrl, ps);
                    }
                    else
                    {
                        urlPath = requestUrl;
                    }
                }

                byte[] bytes = System.Text.Encoding.GetEncoding(encoding).GetBytes(ps);

                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(urlPath);
                request.Referer = refere;
                request.Timeout = timeout * 1000;
                request.Method = isPost ? "POST" : "GET";
                request.Credentials = CredentialCache.DefaultCredentials;

                if (isPost)
                {
                    request.ContentType = "application/x-www-form-urlencoded";
                    request.ContentLength = bytes.Length;

                    Stream requestStream = request.GetRequestStream();
                    requestStream.Write(bytes, 0, bytes.Length);
                    requestStream.Close();
                }

                // 获取Internet资源的响应
                HttpWebResponse response = (HttpWebResponse)request.GetResponse();

                // 从Internet资源返回数据流
                Stream responseStream = response.GetResponseStream();
                if (responseStream != null)
                {
                    // 读取数据流
                    StreamReader reader = new StreamReader(responseStream, System.Text.Encoding.GetEncoding(encoding));

                    // 读取数据
                    result = reader.ReadToEnd();
                    reader.Close();
                    responseStream.Close();
                    request.Abort();
                    response.Close();
                    return result.Trim();
                }
            }
            catch (Exception ex)
            {
                msg = ex.Message + ex.StackTrace;
            }

            return result;
        }
    }
}

 

控制台调用:

static void Main(string[] args)
        {
            string result = string.Empty;

            string url = "http://15013189090.oicp.net:8888/XXXX/XXXXX.jsp";
            List<string> parameters = new List<string>();

            // 读取文件
            FileStream aFile = new FileStream("xml.txt", FileMode.Open);
            StreamReader sr = new StreamReader(aFile);
            string str = sr.ReadToEnd();
            sr.Close();

            // 发送请求
            parameters.Add("orderXml=" + str);
            string msg = string.Empty;
            result = WebCommon.HttpWebRequest(url, null, 50, true, out msg, parameters.ToArray());

            Console.WriteLine(result);
        }

 

通过WebRequest创建一个请求后,可以通过请求来获取HttpWebResponse。然后通过HttpWebResponse.StatusCode来判断当前错误,也可以得到一些精确的消息。

代码详细列表:

成员名称

说明

Continue

等效于 HTTP 状态 100。Continue指示客户端可能继续其请求。

SwitchingProtocols

等效于 HTTP 状态 101。SwitchingProtocols指示正在更改协议版本或协议。

OK

等效于 HTTP 状态 200。OK指示请求成功,且请求的信息包含在响应中。这是最常接收的状态代码。

Created

等效于 HTTP 状态 201。Created指示请求导致在响应被发送前创建新资源。

Accepted

等效于 HTTP 状态 202。Accepted指示请求已被接受做进一步处理。

NonAuthoritativeInformation

等效于 HTTP 状态 203。NonAuthoritativeInformation指示返回的元信息来自缓存副本而不是原始服务器,因此可能不正确。

NoContent

等效于 HTTP 状态 204。NoContent指示已成功处理请求并且响应已被设定为无内容。

ResetContent

等效于 HTTP 状态 205。ResetContent指示客户端应重置(或重新加载)当前资源。

PartialContent

等效于 HTTP 状态 206。PartialContent指示响应是包括字节范围的 GET 请求所请求的部分响应。

MultipleChoices

等效于 HTTP 状态 300。MultipleChoices指示请求的信息有多种表示形式。默认*作是将此状态视为重定向,并遵循与此响应关联的 Location 头的内容。

Ambiguous

等效于 HTTP 状态 300。Ambiguous指示请求的信息有多种表示形式。默认*作是将此状态视为重定向,并遵循与此响应关联的 Location 头的内容。

MovedPermanently

等效于 HTTP 状态 301。MovedPermanently指示请求的信息已移到Location 头中指定的 URI 处。接收到此状态时的默认*作为遵循与响应关联的Location 头。

Moved

等效于 HTTP 状态 301。Moved指示请求的信息已移到 Location 头中指定的URI 处。接收到此状态时的默认*作为遵循与响应关联的 Location 头。原始请求方法为 POST 时,重定向的请求将使用 GET 方法。

Found

等效于 HTTP 状态 302。Found指示请求的信息位于 Location 头中指定的URI 处。接收到此状态时的默认*作为遵循与响应关联的 Location 头。原始请求方法为 POST 时,重定向的请求将使用 GET 方法。

Redirect

等效于 HTTP 状态 302。Redirect指示请求的信息位于 Location 头中指定的URI 处。接收到此状态时的默认*作为遵循与响应关联的 Location 头。原始请求方法为 POST 时,重定向的请求将使用 GET 方法。

SeeOther

等效于 HTTP 状态 303。作为 POST 的结果,SeeOther将客户端自动重定向到 Location 头中指定的 URI。用 GET 生成对 Location 头所指定的资源的请求。

RedirectMethod

等效于 HTTP 状态 303。作为 POST 的结果,RedirectMethod将客户端自动重定向到 Location 头中指定的 URI。用 GET 生成对 Location 头所指定的资源的请求。

NotModified

等效于 HTTP 状态 304。NotModified指示客户端的缓存副本是最新的。未传输此资源的内容。

UseProxy

等效于 HTTP 状态 305。UseProxy指示请求应使用位于 Location 头中指定的URI 的代理服务器。

Unused

等效于 HTTP 状态 306。Unused是未完全指定的 HTTP/1.1 规范的建议扩展。

TemporaryRedirect

等效于 HTTP 状态 307。TemporaryRedirect指示请求信息位于 Location 头中指定的 URI 处。接收到此状态时的默认*作为遵循与响应关联的 Location头。原始请求方法为 POST 时,重定向的请求还将使用 POST 方法。

RedirectKeepVerb

等效于 HTTP 状态 307。RedirectKeepVerb指示请求信息位于 Location 头中指定的 URI 处。接收到此状态时的默认*作为遵循与响应关联的 Location 头。原始请求方法为 POST 时,重定向的请求还将使用 POST 方法。

BadRequest

等效于 HTTP 状态 400。BadRequest指示服务器未能识别请求。如果没有其他适用的错误,或者如果不知道准确的错误或错误没有自己的错误代码,则发送BadRequest

Unauthorized

等效于 HTTP 状态 401。Unauthorized指示请求的资源要求身份验证。WWW-Authenticate 头包含如何执行身份验证的详细信息。

PaymentRequired

等效于 HTTP 状态 402。保留PaymentRequired以供将来使用。

Forbidden

等效于 HTTP 状态 403。Forbidden指示服务器拒绝满足请求。

NotFound

等效于 HTTP 状态 404。NotFound指示请求的资源不在服务器上。

MethodNotAllowed

等效于 HTTP 状态 405。MethodNotAllowed指示请求的资源上不允许请求方法(POST 或 GET)。

NotAcceptable

等效于 HTTP 状态 406。NotAcceptable指示客户端已用 Accept 头指示将不接受资源的任何可用表示形式。

ProxyAuthenticationRequired

等效于 HTTP 状态 407。ProxyAuthenticationRequired指示请求的代理要求身份验证。Proxy-authenticate 头包含如何执行身份验证的详细信息。

RequestTimeout

等效于 HTTP 状态 408。RequestTimeout指示客户端没有在服务器期望请求的时间内发送请求。

Conflict

等效于 HTTP 状态 409。Conflict指示由于服务器上的冲突而未能执行请求。

Gone

等效于 HTTP 状态 410。Gone指示请求的资源不再可用。

LengthRequired

等效于 HTTP 状态 411。LengthRequired指示缺少必需的 Content-length头。

PreconditionFailed

等效于 HTTP 状态 412。PreconditionFailed指示为此请求设置的条件失败,且无法执行此请求。条件是用条件请求标头(如 If-Match、If-None-Match 或 If-Unmodified-Since)设置的。

RequestEntityTooLarge

等效于 HTTP 状态 413。RequestEntityTooLarge指示请求太大,服务器无法处理。

RequestUriTooLong

等效于 HTTP 状态 414。RequestUriTooLong指示 URI 太长。

UnsupportedMediaType

等效于 HTTP 状态 415。UnsupportedMediaType指示请求是不支持的类型。

RequestedRangeNotSatisfiable

等效于 HTTP 状态 416。RequestedRangeNotSatisfiable指示无法返回从资源请求的数据范围,因为范围的开头在资源的开头之前,或因为范围的结尾在资源的结尾之后。

ExpectationFailed

等效于 HTTP 状态 417。ExpectationFailed指示服务器未能符合 Expect 头中给定的预期值。

InternalServerError

等效于 HTTP 状态 500。InternalServerError指示服务器上发生了一般错误。

NotImplemented

等效于 HTTP 状态 501。NotImplemented指示服务器不支持请求的函数。

BadGateway

等效于 HTTP 状态 502。BadGateway指示中间代理服务器从另一代理或原始服务器接收到错误响应。

ServiceUnavailable

等效于 HTTP 状态 503。ServiceUnavailable指示服务器暂时不可用,通常是由于过多加载或维护。

GatewayTimeout

等效于 HTTP 状态 504。GatewayTimeout指示中间代理服务器在等待来自另一个代理或原始服务器的响应时已超时。

HttpVersionNotSupported

等效于 HTTP 状态 505。HttpVersionNotSupported指示服务器不支持请求的 HTTP 版本。

 

参考资料:

  http://www.cnblogs.com/webman/archive/2006/11/17/564106.html

  http://blog.csdn.net/sjj2011/article/details/7822393

posted @ 2015-05-26 13:27  紫清婷  阅读(...)  评论(...编辑  收藏