HTTP请求中的Body构建——.NET客户端调用JAVA服务进行文件上传
PS:今日的第二篇,当日事还要当日毕:)
http的POST请求发送的内容在Body中,因此有时候会有我们自己构建body的情况。
JAVA使用http—post上传file时,spring框架中有HttpEntity类封装了http请求中的Body内容。JAVA客户端调用时非常方便,直接将File对象赋值进去就可以了。
C#中没有找到有类似的封装的(有发现的大神麻烦告知一声:)),HttpWebRequest是原始的http请求类,因此Body中的内容只能自己写入。
首先来看下http请求的内容:
POST /forwardOrder/applyRefund HTTP/1.1
Host: XXXX
Connection: keep-alive
Content-Length: 3478080
Cache-Control: max-age=0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Origin: http://192.168.1.115:3800
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryHUq1k5ZLV25EmvgR
Referer: http://192.168.1.115:3800/forwardOrder/refundOrder?id=160722103139001234
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.8
Cookie: JSESSIONID=52F3D94B82F97240D5A4BBCA2FB08969;
------WebKitFormBoundaryHUq1k5ZLV25EmvgR
Content-Disposition: form-data; name="condition"
{"orderId":"160722103139001234","fileName":"C:\\fakepath\\12349.jpg"}
------WebKitFormBoundaryHUq1k5ZLV25EmvgR
Content-Disposition: form-data; name="file"; filename="12349.jpg"
Content-Type: image/jpeg
����
红色的是HttpHeader的内容,boundary定义了body的分割符。
蓝色的就是我们的Body了,每一个参数使用boundary来进行分割。
特殊的例如文件参数,需要加上Content-Type描述。
乱码部分就是我们的文件字节流了。
最后注意换行和空格的写入。
C#代码示例:
1 /// <summary> 2 /// 上传文件操作 3 /// </summary> 4 /// <param name="fileStream"> 文件流</param> 5 /// <param name="url"> 上传地址</param> 6 /// <param name="fileName"> 文件名</param> 7 /// <param name="contenttype"> 上下文类型 </param> 8 /// <returns> 返回值</returns> 9 private Dictionary <string, string> UploadFileEx(Stream fileStream, string url, string fileName, string contenttype) 10 { 11 Dictionary<string , string> result = new Dictionary <string, string>(); 12 13 if ((contenttype == null ) || (contenttype.Length == 0)) 14 { 15 contenttype = "application/octet-stream" ; 16 } 17 18 Uri uri = new Uri(url); 19 string boundary = "----" + DateTime.Now.Ticks.ToString( "x"); 20 HttpWebRequest webrequest = (HttpWebRequest )WebRequest.Create(uri); 21 webrequest.ContentType = "multipart/form-data; boundary=" + boundary; 22 webrequest.Method = "POST"; 23 24 // 构建POST消息头,除文件之外的键值对都需要赋值 25 StringBuilder sb = new StringBuilder(); 26 sb.AppendFormat( "--{0}", boundary); 27 sb.AppendLine( string.Empty); 28 sb.Append( "Content-Disposition: form-data; name=\"uptype\";" ); 29 sb.AppendLine( string.Empty); 30 sb.AppendLine( string.Empty); 31 sb.Append( "clbuss"); 32 sb.AppendLine( string.Empty); 33 34 sb.AppendFormat( "--{0}", boundary); 35 sb.AppendLine( string.Empty); 36 sb.Append( "Content-Disposition: form-data; name=\"fileName\";" ); 37 sb.AppendLine( string.Empty); 38 sb.AppendLine( string.Empty); 39 sb.Append(fileName); 40 sb.AppendLine( string.Empty); 41 42 sb.AppendFormat( "--{0}", boundary); 43 sb.AppendLine( string.Empty); 44 sb.AppendFormat( "Content-Disposition: form-data; name=\"file\"; filename=\"{0}\"" , fileName); 45 sb.AppendLine( string.Empty); 46 sb.AppendFormat( "Content-Type: {0}", contenttype); 47 sb.AppendLine( string.Empty); 48 sb.AppendLine( string.Empty); 49 50 string postHeader = sb.ToString(); 51 byte[] postHeaderBytes = Encoding .UTF8.GetBytes(postHeader); 52 53 // 构建POST消息尾 54 StringBuilder endSb = new StringBuilder(); 55 endSb.AppendLine( string.Empty); 56 endSb.AppendFormat( "--{0}", boundary); 57 byte[] boundaryBytes = Encoding .UTF8.GetBytes(endSb.ToString()); 58 long length = postHeaderBytes.Length + fileStream.Length + boundaryBytes.Length; 59 webrequest.ContentLength = length; 60 Stream requestStream = webrequest.GetRequestStream(); 61 62 // 写入消息头 63 requestStream.Write(postHeaderBytes, 0, postHeaderBytes.Length); 64 65 // 写入文件内容 66 byte[] buffer = new byte[checked(( uint)Math .Min(4096, (int)fileStream.Length))]; 67 int bytesRead = 0; 68 69 while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0) 70 { 71 requestStream.Write(buffer, 0, bytesRead); 72 } 73 74 // 写入消息尾 75 requestStream.Write(boundaryBytes, 0, boundaryBytes.Length); 76 WebResponse responce = webrequest.GetResponse(); 77 Stream s = responce.GetResponseStream(); 78 StreamReader sr = new StreamReader(s); 79 string resStr = sr.ReadToEnd(); 80 Dictionary<string , object> resDic = JsonConvert.DeserializeObject<Dictionary <string, object>>(resStr); 81 if (resDic["code" ].ToString() == "1") 82 { 83 Dictionary<string , string> resDetail = JsonConvert.DeserializeObject<Dictionary <string, string>>(resDic["content" ].ToString()); 84 if (resDetail["code" ] == "1") 85 { 86 result.Add( "issucess", "1" ); 87 result.Add( "address", BaseSysParamCache .GetSysParam("ShareUploadImgUrl") + resDetail["path" ]); 88 } 89 else 90 { 91 result.Add( "issucess", "0" ); 92 result.Add( "msg", resDetail["msg" ]); 93 } 94 } 95 else 96 { 97 result.Add( "issucess", "0" ); 98 result.Add( "msg", resDic["message" ].ToString()); 99 } 100 101 return result; 102 }
http请求对于JAVA和C#本身其实并无区分,只是使用的方式不同而已。
无论何种情况,源生的HTTP请求内容都是通用的。