一般處理程序
HTTP協議
連接:瀏覽器和服務器之間的連接,當請求完畢后,會關閉連接。
請求(Request):瀏覽器向服務器發出請求,我需要什么。
GET / HTTP/1.1表示向服務器用GET方式請求首頁,使用HTTP/1.1協議
User-Agent(簡稱UA)為瀏覽器的版本信息。通過這個信息可以讀取瀏覽器是IE還是FireFox、支持的插件、.Net版本等。看看IE和Chrome的UserAgent不一樣
Referer:來源頁面、所屬頁面
Accept-Encoding:服務器支持什么壓縮算法。Accept-Language:瀏覽器支持什么語言。
響應(Response):服務器響應瀏覽器,返回瀏覽器請求的數據。
響應碼:“200” : OK; “302” : Found 暫時轉移,用於重定向, Response.Redirect()會讓瀏覽器再請求一次重定向的地址,重定向的請求是Get方式; "404" : Not Found 未找到。500 服務器錯誤(一般服務器出現異常),通過報錯信息找出異常的點。403:客戶端訪問未被授權。304(服務器把文件的修改日期通過Last-Modified返回給瀏覽器,瀏覽器緩存這個文件,下次向服務器請求這個文件的時候,通過If-Modified-Since問服務器說“我本地的文件的修改日期是。。。”,服務器端如果發現文件還是那個文件,則告訴瀏覽器(304 Not Modified)文件沒修改,還用本地的吧。ctrl+f5)。2xx:沒問題;3xx代表瀏覽器需要干點啥;4***瀏覽器的問題;5xx服務器錯誤
服務器通過Content-Type告訴客戶端響應的數據的類型,這樣瀏覽器就根據返回數據的類型來進行不同的處理。
GET:通過url傳值,有長度限制。
POST:通過HTTP報文體。
數據格式。服務端文件名后跟着“?”,由於客戶端可能向服務器端提交多個鍵值對,鍵值對之間用“&”進行分割,如果URL中有漢字、特殊符號等,則需要對URL進行編碼。
Request
通過Form獲取POST報文體:
1 //context.Request.Form["name"]獲得通過報文體傳輸的參數 2 string name = context.Request.Form["name"]; 3 string age = context.Request.Form["age"];
通過QueryString獲取Get方式中的值:
1 //context.Request.QueryString獲得GET方式中“GET /Test.ashx?id=5 HTTP/1.1”中的 2 //"id=5"值 3 string name = context.Request.QueryString["name"]; 4 string age = context.Request.QueryString["age"];
同時獲取POST和Get中的值:(同時對Form和QueryString進行查詢)
1 //context.Request["name"]無論是Get還是Post都能獲得 2 string name = context.Request["name"];//[""]索引器 3 string age = context.Request["age"];
服務器獲取客戶端信息:
1 //服務器想獲得瀏覽器的某些信息:只要瀏覽器沒提交,那么你就獲得不了這些信息。服務器無法得知用戶是否裝了PS,服務器無法得知用戶什么時候開機。 2 context.Response.Write("------------------------\n"); 3 for (int i = 0; i < context.Request.Headers.AllKeys.Length; i++)//Request.Headers請求報文頭 4 { 5 string key = context.Request.Headers.AllKeys[i]; 6 string value = context.Request.Headers[key]; 7 context.Response.Write(key+"="+value+"\n"); 8 } 9 context.Response.Write("------------------------\n"); 10 11 context.Response.Write(context.Request.HttpMethod + "\n"); 12 //context.Response.Write(context.Request.InputStream);//請求報文體的流 13 context.Response.Write(context.Request.Path + "\n"); 14 context.Response.Write(context.Request.QueryString + "\n"); 15 context.Response.Write(context.Request.PhysicalPath + "\n");//被請求的文件的服務器上的物理路徑 16 context.Response.Write(context.Request.UserAgent + "\n"); 17 context.Response.Write(context.Request.UserHostAddress + "\n");//客戶端的IP地址 18 context.Response.Write(context.Request.UrlReferrer + "\n"); 19 context.Response.Write(String.Join(",",context.Request.UserLanguages) + "\n");//瀏覽器支持什么語言
HttpContext:和本次請求相關對象的一個上下文對象,一般通過它過去其他對象。在HttpHandler的ProcessRequest方法中可以通過方法的context參數獲得對象。在其他地方可以通過HttpContext.Current拿到當前請求堆棧中的HttpContext對象。
public void ProcessRequest(HttpContext context)
Response
ContentType;OutputStream輸出流;
End()將當前所有緩沖的輸出發送到客戶端,停止該頁的執行。通過對End()進行try,發現是是拋出了異常。
1 context.Response.End(); 2 //因為End()拋出了一個ThreadAbortException,所以不會繼續向下執行了 3 //因為異常處理效率低,所以盡可能的不用Response.End(); 4 try 5 { 6 context.Response.End();//終止HttpHandler的執行,不再向下執行了 7 } 8 catch (Exception ex) 9 { 10 11 }
context. Server
Server是一個HttpServerUtility類型(提供用於處理 Web 請求的 Helper 方法)的對象,不是一個類名。
MapPath:MapPath("~/a.htm")將虛擬路徑(~代表項目根目錄)轉換為磁盤上的絕對路徑,操作項目中的文件使用。
1 FileInfo fi = new FileInfo(@"E:\asp.netcorecode\ASPNETCore\Web1\*.jpg"); 2 FileInfo fi = new FileInfo(@"*.jpg");//永遠不要用相對路徑,容易進坑 3 string filepath = context.Server.MapPath("~/*.jpg"); 4 //得到文件在服務器磁盤上的絕對路徑。~表示網站根目錄 5 FileInfo fi = new FileInfo(filepath); 6 context.Response.Write(fi.Length);
HtmlEncode、 HtmlDecode:HTML編碼解碼。Encode為的是把特殊字符轉義顯示。
1 string cscode = "hello List<T> list = new List<T>();"; 2 //HtmlEncode:把<>等特殊字符轉換為html中的轉義字符 3 string enCodeCSCode = context.Server.HtmlEncode(cscode); 4 //context.Response.Write(cscode); 5 context.Response.Write(enCodeCSCode); 6 context.Response.Write("</body></html>"); 7 string s = "hello List<T> list = new List<T>();"; 8 string s1 = context.Server.HtmlDecode(s);//HtmlEncode的反過程 9 context.Response.Write(s1);
UrlEncode、 UrlDecode:url編碼解碼。漢字、特殊字符(空格、尖括號)等通過Url傳遞的時候要編碼。
1 //數據傳輸前最好采用UrlEncode編碼 2 string s = "hello 世界<>"; 3 string s1 = context.Server.UrlEncode(s); 4 context.Response.Write(s1);
文件下載
導出數據動態生成文本,不會彈出保存提示框。增加報文頭: context.Response.AddHeader("Content-Disposition", "attachment;filename="+context.Server.UrlEncode("動態文件.txt"));
1 context.Response.ContentType = "image/jpeg"; 2 using (Bitmap bmp = new Bitmap(500, 200))//創建一個尺寸為500*500的內存圖片 3 using (Graphics g = Graphics.FromImage(bmp))//得到圖片的畫布 4 using (Font font = new Font(FontFamily.GenericSerif, 30)) 5 { 6 HttpRequest request = context.Request; 7 g.DrawString("IP:" + request.UserHostAddress, font, Brushes.Red, 0, 0); 8 g.DrawString("瀏覽器:" + request.Browser.Browser + request.Browser.Version, font, Brushes.Red, 0, 50); 9 g.DrawString("操作系統:" + request.Browser.Platform, font, Brushes.Red, 0, 100); 10 bmp.Save(context.Response.OutputStream, ImageFormat.Jpeg);//圖片保存到輸出流 11 } 12 //增加Content-Disposition是告訴瀏覽器,這個返回的內容是“附件形式”要給用戶保存 13 //filename是建議的文件名 14 context.Response.AddHeader("Content-Disposition", "attachment;filename=" + 15 context.Server.UrlEncode("動態文件.txt"));
文件上傳
如果要進行文件上傳,則需要采用method="post",並且要設定enctype="multipart/form-data"。提交報文格式會發生變化。用戶上傳的文件盡量“不落地”,也就是不保存到本地,可以避免:上傳文件把服務器撐爆。
1 context.Response.ContentType = "text/html"; 2 HttpPostedFile file1 = context.Request.Files["file1"];//上傳的文件,可以是多個 3 HttpPostedFile filehaha = context.Request.Files["filehaha"]; 4 string name = context.Request["name"]; 5 //HttpPostedFile.FileName是文件名,通過查看報文發現,FileName是瀏覽器提交過去的 6 if (file1.ContentLength > 1024 * 1024) 7 { 8 context.Response.Write("文件不能超過1MB"); 9 return; 10 } 11 12 //為什么根據ContentType判斷文件類型不安全。 13 //因為ContentType是瀏覽器提交的,是可以造假的,文件內容是病毒,filename是1.exe 14 //ContentType偽造成了"image/jpeg"。 15 /* 16 if(file1.ContentType!="image/jpeg"&&file1.ContentType!="image/gif" 17 &&file1.ContentType!="image/png") 18 { 19 context.Response.Write("文件類型不允許"); 20 return; 21 }*/ 22 string fileExt = Path.GetExtension(file1.FileName); 23 if(fileExt!=".jpg"&&fileExt!=".gif"&&fileExt!=".png") 24 { 25 context.Response.Write("文件類型不允許"); 26 return; 27 } 28 29 30 string localFileName = context.Server.MapPath("~/upload") + "/" + file1.FileName; 31 file1.SaveAs(localFileName);//把文件保存到服務器上 32 context.Response.Write(localFileName+"<br/>"); 33 context.Response.Write(name);
