In C #, there is an httpwebrequest class, which can be easily used to obtain HTTP requests. However, this class does not provide a convenient way to obtain data in post mode. Many people provide solutions on the Internet, but they are all different. Here I will summarize the methods I have used and share them with you.
Essence of this article: When post is implemented, the key-value of the string can be included, and files can also be included.
Post Data Format
When the POST request submits data, the most important thing is to put the key-value data in the HTTP request stream, while httpwebrequest does not provide a property or something that allows us to freely add key-value, therefore, the data must be constructed manually.
According to RFC 2045, the data format of an http post is as follows:
Content-Type: multipart/form-data; boundary=AaB03x --AaB03x Content-Disposition: form-data; name="submit-name" Larry --AaB03x Content-Disposition: form-data; name="file"; filename="file1.dat" Content-Type: application/octet-stream ... contents of file1.dat ... --AaB03x--
The detailed explanation is as follows:
Content-Type: multipart/form-data; boundary = aab03x
As shown above, first declare the data type as multipart/form-data, and then define the boundary string aab03x. This boundary string is used to distinguish each data in the following sections. You can define it as needed, however, it is best to use characters that do not usually appear in data such as dashes. Then there is a line break.
Note: The line break defined in post is \ r \ n
-- Aab03x
This is a boundary string. Note that two hyphens (--) must be added before each boundary to keep up with the linefeed.
Content-Disposition: Form-data; name = "Submit-name"
Here is the string type data in the key-value data. Submit-name is the key in the key-value data. Line breaks are also required.
Larry
This is the value in the key-value data.
-- Aab03x
Boundary, indicating the end of the data.
Content-Disposition: Form-data; name = "file"; filename = "file1.dat"
This indicates another data. Its key is file and its file name is file1.dat. Note: There is no semicolon at the end.
Content-Type: Application/octet-stream
This identifies the file type. Application/octet-stream indicates binary data.
... Contents of file1.dat...
This is the file content. Binary data.
-- Aab03x --
The delimiter after the end of the data. Note that because there is no data after the end, you need to append a "--" to indicate the end.
C # Post Data Function
After understanding the format, we can easily write C # code. As follows:
Private Static string httppostdata (string URL, int timeout, string filekeyname, string filepath, namevaluecollection stringdict) {string responsecontent; var memstream = new memorystream (); var webrequest = (httpwebrequest) webrequest. create (URL); // The boundary var boundary = "-------------" + datetime. now. ticks. tostring ("X"); // The boundary var beginboundary = encoding. ASCII. getbytes ("--" + boundary + "\ r \ n "); VaR filestream = new filestream (filepath, filemode. open, fileaccess. read); // The final Terminator var endboundary = encoding. ASCII. getbytes ("--" + boundary + "-- \ r \ n"); // sets the attribute webrequest. method = "Post"; webrequest. timeout = timeout; webrequest. contenttype = "multipart/form-data; boundary =" + boundary; // write the file const string filepartheader = "content-Disposition: Form-data; name = \ "{0} \"; filename = \ "{1} \" \ r \ n "+ "Content-Type: Application/octet-stream \ r \ n"; var header = string. format (filepartheader, filekeyname, filepath); var headerbytes = encoding. utf8.getbytes (header); memstream. write (beginboundary, 0, beginboundary. length); memstream. write (headerbytes, 0, headerbytes. length); var buffer = new byte [1024]; int bytesread; // = 0 while (bytesread = filestream. read (buffer, 0, buffer. length ))! = 0) {memstream. write (buffer, 0, bytesread);} // key var stringkeyheader = "\ r \ n --" + boundary + "\ r \ ncontent-Disposition: form-data; name = \ "{0} \" "+" \ r \ n {1} \ r \ n "; foreach (byte [] formitembytes in from string key in stringdict. keys select string. format (stringkeyheader, key, stringdict [Key]) into formitem select encoding. utf8.getbytes (formitem) {memstream. write (formitembytes, 0, formitembytes. length);} // write the final end boundary of memstream. write (endboundary, 0, endboundary. length); webrequest. contentlength = memstream. length; var requeststream = webrequest. getrequeststream (); memstream. position = 0; var tempbuffer = new byte [memstream. length]; memstream. read (tempbuffer, 0, tempbuffer. length); memstream. close (); requeststream. write (tempbuffer, 0, tempbuffer. length); requeststream. close (); var httpwebresponse = (httpwebresponse) webrequest. getresponse (); Using (VAR httpstreamreader = new streamreader (httpwebresponse. getresponsestream (), encoding. getencoding ("UTF-8") {responsecontent = httpstreamreader. readtoend ();} filestream. close (); httpwebresponse. close (); webrequest. abort (); Return responsecontent ;}
References
- Rfc2045: http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.
- Http://stackoverflow.com/questions/566462/upload-files-with-httpwebrequest-multipart-form-data
- Via: http://hi.baidu.com/zkbob22/blog/item/0638f93931209ae0b211c7b8.html