HttpWebRequest類

原文地址       

  HttpWebRequest類與HttpRequest類的區別。

  HttpRequest類的對象用於服務器端,獲取客戶端傳來的請求的信息,包括HTTP報文傳送過來的所有信息。而HttpWebRequest用於客戶端,拼接請求的HTTP報文併發送等。

  HttpWebRequest這個類非常強大,強大的地方在於它封裝了幾乎HTTP請求報文裏需要用到的東西,以致於能夠能夠發送任意的HTTP請求並獲得服務器響應(Response)信息。採集信息常用到這個類。在學習這個類之前,首先有必要了解下HTTP方面的知識。

一、簡單示例

  我們先來一個最簡單的,就是緊緊輸入一個網址就獲取響應。代碼如下:

複製代碼
    class Program
    {
        static void Main(string[] args)
        {
            HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create("http://www.baidu.com");    //創建一個請求示例
            HttpWebResponse response  = (HttpWebResponse)request.GetResponse();  //獲取響應,即發送請求
            Stream responseStream = response.GetResponseStream();
            StreamReader streamReader = new StreamReader(responseStream, Encoding.UTF8);
            string html = streamReader.ReadToEnd();
            Console.WriteLine(html);

            Console.ReadKey();
        }
    }
複製代碼

  OK,就是這麼簡單了,真的這麼簡單嗎?發送一個HTTP請求真的這麼簡單。但是要做出很多功能就不簡單了。你需要詳細瞭解下HTTP方面的知識,比如HTTP請求報文之類的。

二、模擬登錄

  下面來個複雜點的,這次是獲取登錄之後的頁面。登錄之後的請求用什麼實現呢?呵呵,用到是cookie。在拼接HTTP請求的時候,連着cookie也發送過去。

複製代碼
namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            HttpHeader header = new HttpHeader();
            header.accept = "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/x-silverlight, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/x-ms-application, application/x-ms-xbap, application/vnd.ms-xpsdocument, application/xaml+xml, application/x-silverlight-2-b1, */*";
            header.contentType = "application/x-www-form-urlencoded";
            header.method = "POST";
            header.userAgent = "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022)";
            header.maxTry = 300;

            //在這裏自己拼接一下Cookie,不用複製過來的那個GetCookie方法了,原來的那個寫法還是比較嚴謹的
            CookieContainer cc = new CookieContainer();
            Cookie cUserName = new Cookie("cSpaceUserEmail", "742783833%40qq.com");
            cUserName.Domain = ".7soyo.com";
            Cookie cUserPassword = new Cookie("cSpaceUserPassWord", "4f270b36a4d3e5ee70b65b1778e8f793");
            cUserPassword.Domain = ".7soyo.com";
            cc.Add(cUserName);
            cc.Add(cUserPassword);

            string html = HTMLHelper.GetHtml("http://user.7soyo.com/CollectUser/List", cc, header);
            FileStream fs = new FileStream(@"D:\123.txt",FileMode.CreateNew,FileAccess.ReadWrite);
            fs.Write(Encoding.UTF8.GetBytes(html),0,html.Length);
            fs.Flush();
            fs.Dispose();

            Console.WriteLine(html);

            Console.ReadKey();
        }
    }

    public class HTMLHelper
    {
        /// <summary>
        /// 獲取CooKie
        /// </summary>
        /// <param name="loginUrl"></param>
        /// <param name="postdata"></param>
        /// <param name="header"></param>
        /// <returns></returns>
        public static CookieContainer GetCooKie(string loginUrl, string postdata, HttpHeader header)
        {
            HttpWebRequest request = null;
            HttpWebResponse response = null;
            try
            {
                CookieContainer cc = new CookieContainer();
                request = (HttpWebRequest)WebRequest.Create(loginUrl);
                request.Method = header.method;
                request.ContentType = header.contentType;
                byte[] postdatabyte = Encoding.UTF8.GetBytes(postdata);     //提交的請求主體的內容
                request.ContentLength = postdatabyte.Length;    //提交的請求主體的長度
                request.AllowAutoRedirect = false;
                request.CookieContainer = cc;
                request.KeepAlive = true;

                //提交請求
                Stream stream;
                stream = request.GetRequestStream();
                stream.Write(postdatabyte, 0, postdatabyte.Length);     //帶上請求主體
                stream.Close();

                //接收響應
                response = (HttpWebResponse)request.GetResponse();      //正式發起請求
                response.Cookies = request.CookieContainer.GetCookies(request.RequestUri);

                CookieCollection cook = response.Cookies;
                //Cookie字符串格式
                string strcrook = request.CookieContainer.GetCookieHeader(request.RequestUri);

                return cc;
            }
            catch (Exception ex)
            {

                throw ex;
            }
        }

        /// <summary>
        /// 獲取html
        /// </summary>
        /// <param name="getUrl"></param>
        /// <param name="cookieContainer"></param>
        /// <param name="header"></param>
        /// <returns></returns>
        public static string GetHtml(string getUrl, CookieContainer cookieContainer, HttpHeader header)
        {
            Thread.Sleep(1000);
            HttpWebRequest httpWebRequest = null;
            HttpWebResponse httpWebResponse = null;
            try
            {
                httpWebRequest = (HttpWebRequest)HttpWebRequest.Create(getUrl);
                httpWebRequest.CookieContainer = cookieContainer;
                httpWebRequest.ContentType = header.contentType;
                httpWebRequest.ServicePoint.ConnectionLimit = header.maxTry;
                httpWebRequest.Referer = getUrl;
                httpWebRequest.Accept = header.accept;
                httpWebRequest.UserAgent = header.userAgent;
                httpWebRequest.Method = "GET";
                httpWebResponse = (HttpWebResponse)httpWebRequest.GetResponse();
                Stream responseStream = httpWebResponse.GetResponseStream();
                StreamReader streamReader = new StreamReader(responseStream, Encoding.UTF8);
                string html = streamReader.ReadToEnd();
                streamReader.Close();
                responseStream.Close();
                httpWebRequest.Abort();
                httpWebResponse.Close();
                return html;
            }
            catch (Exception e)
            {
                if (httpWebRequest != null) httpWebRequest.Abort();
                if (httpWebResponse != null) httpWebResponse.Close();
                return string.Empty;
            }
        }
    }

    public class HttpHeader
    {
        public string contentType { get; set; }

        public string accept { get; set; }

        public string userAgent { get; set; }

        public string method { get; set; }

        public int maxTry { get; set; }
    }
}
複製代碼

  這樣獲取到的就是登錄之後的頁面了。

三、模擬表單提交

  再來一個例子,運用HttpWebRequest來模擬表單的提交,先新建一個MVC項目,裏面只有這些代碼:

複製代碼
        [HttpPost]
        public ActionResult Index(string userName,string userPassword)
        {
            string str = "你提交過來的用戶名是:" + userName + ",密碼是: " + userPassword;
            Response.Write(str);
            return View();
        }
複製代碼

  然後啓動該項目,再新建另外一個項目,用於模擬提交表單,然後注意路徑填寫的是剛纔建的那個MVC項目。

複製代碼
       static void Main(string[] args)
        {
            HttpWebRequest request = null;
            HttpWebResponse response = null;
            CookieContainer cc = new CookieContainer();
            request = (HttpWebRequest)WebRequest.Create("http://localhost:2539/");
            request.Method = "POST";
            request.ContentType = "application/x-www-form-urlencoded";
            request.UserAgent = "Mozilla/5.0 (Windows NT 6.1; rv:19.0) Gecko/20100101 Firefox/19.0";

            string requestForm = "userName=1693372175&userPassword=123456";     //拼接Form表單裏的信息
            byte[] postdatabyte = Encoding.UTF8.GetBytes(requestForm);
            request.ContentLength = postdatabyte.Length;
            request.AllowAutoRedirect = false;
            request.CookieContainer = cc;
            request.KeepAlive = true;

            Stream stream;
            stream = request.GetRequestStream();
            stream.Write(postdatabyte, 0, postdatabyte.Length); //設置請求主體的內容
            stream.Close();

            //接收響應
            response = (HttpWebResponse)request.GetResponse();
            Console.WriteLine();

            Stream stream1 = response.GetResponseStream();
            StreamReader sr = new StreamReader(stream1);
            Console.WriteLine(sr.ReadToEnd());
        
            Console.ReadKey();
        }
複製代碼

  輸出結果如下所示:

  

四、模擬上傳

  血的教訓,注意路徑不能寫錯,否則在對流進行操作時,Write,就會報錯:

HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://localhost:9170/upload/test");

  客戶端:

複製代碼
    class Program
    {
        /** 
         * 如果要在客戶端向服務器上傳文件,我們就必須模擬一個POST multipart/form-data類型的請求 
         * Content-Type必須是multipart/form-data。 
         * 以multipart/form-data編碼的POST請求格式與application/x-www-form-urlencoded完全不同 
         * multipart/form-data需要首先在HTTP請求頭設置一個分隔符,例如7d4a6d158c9: 
         * 我們模擬的提交要設定 content-type不同於非含附件的post時候的content-type 
         * 這裏需要: ("Content-Type", "multipart/form-data; boundary=ABCD"); 
         * 然後,將每個字段用“--7d4a6d158c9”分隔,最後一個“--7d4a6d158c9--”表示結束。 
         * 例如,要上傳一個title字段"Today"和一個文件C:\1.txt,HTTP正文如下: 
         *  
         * --7d4a6d158c9 
         * Content-Disposition: form-data; name="title" 
         * \r\n\r\n 
         * Today 
         * --7d4a6d158c9 
         * Content-Disposition: form-data; name="1.txt"; filename="C:\1.txt" 
         * Content-Type: text/plain 
         * 如果是圖片Content-Type: application/octet-stream 
         * \r\n\r\n 
         * <這裏是1.txt文件的內容> 
         * --7d4a6d158c9 
         * \r\n 
         * 請注意,每一行都必須以\r\n結束value前面必須有2個\r\n,包括最後一行。 
        */
        static void Main(string[] args)
        {
            string boundary = "----------" + DateTime.Now.Ticks.ToString("x");//元素分割標記 
            StringBuilder sb = new StringBuilder();
            sb.Append("--" + boundary);
            sb.Append("\r\n");
            sb.Append("Content-Disposition: form-data; name=\"file1\"; filename=\"D:\\upload.xml" + "\"");
            sb.Append("\r\n");
            sb.Append("Content-Type: application/octet-stream");
            sb.Append("\r\n");
            sb.Append("\r\n");//value前面必須有2個換行  

            HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://localhost:9170/upload/test");
            request.ContentType = "multipart/form-data; boundary=" + boundary;//其他地方的boundary要比這裏多--  
            request.Method = "POST";

            FileStream fileStream = new FileStream(@"D:\123.xml", FileMode.OpenOrCreate, FileAccess.Read);

            byte[] postHeaderBytes = Encoding.UTF8.GetBytes(sb.ToString());
            byte[] boundaryBytes = Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n");
            //http請求總長度  
            request.ContentLength = postHeaderBytes.Length + fileStream.Length + boundaryBytes.Length;
            Stream requestStream = request.GetRequestStream(); 
            requestStream.Write(postHeaderBytes, 0, postHeaderBytes.Length);
            byte[] buffer = new Byte[checked((uint)Math.Min(4096, (int)fileStream.Length))];
            int bytesRead = 0;
            while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
            {
                requestStream.Write(buffer, 0, bytesRead);
            }
            fileStream.Dispose();
            requestStream.Write(boundaryBytes, 0, boundaryBytes.Length);
            WebResponse webResponse2 = request.GetResponse();
            Stream htmlStream = webResponse2.GetResponseStream();
            string HTML = GetHtml(htmlStream, "UTF-8");
            Console.WriteLine(HTML);
            htmlStream.Dispose();
        }
  }
複製代碼

  測試服務器端地址:

複製代碼
        public ActionResult Test()
        {
            HttpRequest request = System.Web.HttpContext.Current.Request;
            HttpFileCollection FileCollect = request.Files;
            if (FileCollect.Count > 0)          //如果集合的數量大於0
            {
                foreach (string str in FileCollect)
                {
                    HttpPostedFile FileSave = FileCollect[str];  //用key獲取單個文件對象HttpPostedFile
                    string imgName = DateTime.Now.ToString("yyyyMMddhhmmss");
                    string AbsolutePath = FileSave.FileName;
                    FileSave.SaveAs(AbsolutePath);              //將上傳的東西保存
                }
            }
            return Content("鍵值對數目:" + FileCollect.Count);
        }
複製代碼

  

原文傳送門

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章