HTTP请求中的Body构建——.NET客户端调用JAVA服务进行文件上传

时间:2023-03-08 19:58:38
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#代码示例:
         /// <summary>
/// 上传文件操作
/// </summary>
/// <param name="fileStream"> 文件流</param>
/// <param name="url"> 上传地址</param>
/// <param name="fileName"> 文件名</param>
/// <param name="contenttype"> 上下文类型 </param>
/// <returns> 返回值</returns>
private Dictionary <string, string> UploadFileEx(Stream fileStream, string url, string fileName, string contenttype)
{
Dictionary<string , string> result = new Dictionary <string, string>(); if ((contenttype == null ) || (contenttype.Length == ))
{
contenttype = "application/octet-stream" ;
} Uri uri = new Uri(url);
string boundary = "----" + DateTime.Now.Ticks.ToString( "x");
HttpWebRequest webrequest = (HttpWebRequest )WebRequest.Create(uri);
webrequest.ContentType = "multipart/form-data; boundary=" + boundary;
webrequest.Method = "POST"; // 构建POST消息头,除文件之外的键值对都需要赋值
StringBuilder sb = new StringBuilder();
sb.AppendFormat( "--{0}", boundary);
sb.AppendLine( string.Empty);
sb.Append( "Content-Disposition: form-data; name=\"uptype\";" );
sb.AppendLine( string.Empty);
sb.AppendLine( string.Empty);
sb.Append( "clbuss");
sb.AppendLine( string.Empty); sb.AppendFormat( "--{0}", boundary);
sb.AppendLine( string.Empty);
sb.Append( "Content-Disposition: form-data; name=\"fileName\";" );
sb.AppendLine( string.Empty);
sb.AppendLine( string.Empty);
sb.Append(fileName);
sb.AppendLine( string.Empty); sb.AppendFormat( "--{0}", boundary);
sb.AppendLine( string.Empty);
sb.AppendFormat( "Content-Disposition: form-data; name=\"file\"; filename=\"{0}\"" , fileName);
sb.AppendLine( string.Empty);
sb.AppendFormat( "Content-Type: {0}", contenttype);
sb.AppendLine( string.Empty);
sb.AppendLine( string.Empty); string postHeader = sb.ToString();
byte[] postHeaderBytes = Encoding .UTF8.GetBytes(postHeader); // 构建POST消息尾
StringBuilder endSb = new StringBuilder();
endSb.AppendLine( string.Empty);
endSb.AppendFormat( "--{0}", boundary);
byte[] boundaryBytes = Encoding .UTF8.GetBytes(endSb.ToString());
long length = postHeaderBytes.Length + fileStream.Length + boundaryBytes.Length;
webrequest.ContentLength = length;
Stream requestStream = webrequest.GetRequestStream(); // 写入消息头
requestStream.Write(postHeaderBytes, , postHeaderBytes.Length); // 写入文件内容
byte[] buffer = new byte[checked(( uint)Math .Min(, (int)fileStream.Length))];
int bytesRead = ; while ((bytesRead = fileStream.Read(buffer, , buffer.Length)) != )
{
requestStream.Write(buffer, , bytesRead);
} // 写入消息尾
requestStream.Write(boundaryBytes, , boundaryBytes.Length);
WebResponse responce = webrequest.GetResponse();
Stream s = responce.GetResponseStream();
StreamReader sr = new StreamReader(s);
string resStr = sr.ReadToEnd();
Dictionary<string , object> resDic = JsonConvert.DeserializeObject<Dictionary <string, object>>(resStr);
if (resDic["code" ].ToString() == "")
{
Dictionary<string , string> resDetail = JsonConvert.DeserializeObject<Dictionary <string, string>>(resDic["content" ].ToString());
if (resDetail["code" ] == "")
{
result.Add( "issucess", "" );
result.Add( "address", BaseSysParamCache .GetSysParam("ShareUploadImgUrl") + resDetail["path" ]);
}
else
{
result.Add( "issucess", "" );
result.Add( "msg", resDetail["msg" ]);
}
}
else
{
result.Add( "issucess", "" );
result.Add( "msg", resDic["message" ].ToString());
} return result;
}
http请求对于JAVA和C#本身其实并无区分,只是使用的方式不同而已。
无论何种情况,源生的HTTP请求内容都是通用的。