HTTP POST上传文件说明及注意事项

这一阵子因为项目需要要对接别家公司的restful接口,其中有一个接口是上传视频文件。接着上网找找资料。后来文件是上传成功了,但上服务器一看,文件没有后缀,我勒个去,这是什么个鬼。接着继续找资料,最终发现是因为在文件数据后面没加上“\r\n”引起的,特发此博文备忘。在此感谢【小伊同学】的《c#代码发送post请求,上传文件》https://www.cnblogs.com/yinq/p/6045995.html和【imEgo】的《HTTP POST上传文件格式说明》http://blog.sina.com.cn/s/blog_73b633110101jwxm.html。

 1 public static Response FileLoadRequest(string url, string filePath, string rename = "")
 2 {
 3     Response httpResponse = null;
 4     string fileName = FileHelper.GetFileName(filePath);
 5     string boundary = "ceshi";
 6     string Enter = "\r\n";
 7 
 8     HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
 9     request.Method = "POST";
10     request.ContentType = "multipart/form-data;charset=utf8;boundary=" + boundary;  //boundary这个属性很重要
11     //进行Session持久化
12     request.CookieContainer = cookie;
13 
14     #region 将参数写入请求流中
15     Stream RequestStream = request.GetRequestStream();
16     string fileContentStr = "--" + boundary + Enter
17             + "Content-Type:application/octet-stream" + Enter
18             + "Content-Disposition: form-data; name=\"file\"; filename=\"" + fileName + "\"" + Enter + Enter;
19     var fileContentStrByte = Encoding.UTF8.GetBytes(fileContentStr);
20 
21     FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read);
22     byte[] filedata = new byte[fs.Length];
23     fs.Read(filedata, 0, Convert.ToInt32(fs.Length));
24     fs.Close();
25 
26     RequestStream.Write(fileContentStrByte, 0, fileContentStrByte.Length);
27     RequestStream.Write(filedata, 0, filedata.Length);
28 
29     //在文件数据末尾要加上“\r\n”
30     string EndStr1 = Enter;
31     var EndStr1Byte = Encoding.UTF8.GetBytes(EndStr1);
32     RequestStream.Write(EndStr1Byte, 0, EndStr1Byte.Length);
33 
34     if (rename != "")
35     {
36         string fileNameStr = "--" + boundary + Enter
37             + "Content-Disposition: form-data; name=\"file_name\"" + Enter + Enter
38             + rename;
39         var fileNameStrByte = Encoding.UTF8.GetBytes(fileNameStr);
40         RequestStream.Write(fileNameStrByte, 0, fileNameStrByte.Length);
41     }
42 
43     //在流末尾要加上--ceshi--的分隔符
44     string EndStr = Enter + "--" + boundary + "--";
45     var EndStrByte = Encoding.UTF8.GetBytes(EndStr);
46     RequestStream.Write(EndStrByte, 0, EndStrByte.Length);
47     #endregion
48 
49     string responseMessage = string.Empty;
50     try
51     {
52         using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
53         {
54 
55             StreamReader sr = new StreamReader(response.GetResponseStream(), Encoding.UTF8);
56             responseMessage = sr.ReadToEnd();
57             httpResponse = JsonConvert.DeserializeObject<Response>(responseMessage);
58             response.Close();
59         }
60     }
61     catch (WebException ex)
62     {
63         Program.log.Error(string.Format("System.Net.WebException:UrlGetRequest出错,URL='{0}':", request.RequestUri), ex);
64     }
65     catch (Exception ex)
66     {
67         Program.log.Error(string.Format("UrlGetRequest出错,URL='{0}':", request.RequestUri), ex);
68     }
69 
70     return httpResponse;
71 }

下面引用下RFC的Sample:

Content-Type: multipart/form-data, boundary=AaB03x

--AaB03x
Content-Disposition: form-data; name="field1"

Joe Blow
--AaB03x
Content-Disposition: form-data; name="pics"; filename="file1.txt"
Content-Type: text/plain

 ... contents of file1.txt ...
--AaB03x--

首先,在Content-Type中,boundary这个属性一定要加,但boundary属性值随意设置成什么都行,它不会出现在要上传的数据里,只是起到分隔的作用。上面是设置成“Aab03x”。重点来了:每个参数之前需要加上“--boundary”,注意前面有“--”。参数最后结尾要加“--boundary--”。文件数据后要跟上“\r\n”(我就是因为没加“\r\n,所以没有文件后缀”)在上传文件的那一个参数的Content-Type:是根据上传文件的后缀进行设置的,详细对照表请参照:http://tool.oschina.net/commons/。如果不想根据文件后缀进行填充的话,可以直接用“application/octet-stream”。

posted @ 2017-11-29 09:43  龙宫丿  阅读(10199)  评论(0编辑  收藏  举报