RFC 2188: returning values from forms: multipart/form-data. This document describes how to use multiple formats of information in http post messages, it can be used in many rest-based API systems. It can be mixed with multiple data formats and transmitted at a time. Of course, non-text data must be encoded as binary strings.
In the RFC 2387 file, it is pointed out that to transmit information of multiple parameters and mixed data types, you must first set the Content-Type required by HTTP to multipart/form-data, in addition, you need to set a boundary parameter, which is generated by the application itself. It is used to identify the boundary of each piece of data and generate multiple Message parts ), the HTTP server can capture the http post information and expose it to the server using the Common Object Model (ex: Asp. NET Request. form ).
The following is a multipart/form-data message with multiple parameters (Source: RFC 2388 ):
Content-Type: multipart/form-data; boundary = myboundary
...
-- Myboundary
Content-Disposition: Form-data; name = "[parameter-name]"
<Newline>
<Newline>
<Data goes here>
-- Myboundary
Content-Disposition: Form-data; name = "[parameter-name]"
<Newline>
<Newline>
<Data goes here>
-- Myboundary
Content-Disposition: Form-data; name = "[parameter-name]"
Content-Type: image/JPEG
<Newline>
<Newline>
<Image data goes here>
-- Myboundary
The above information seems quite difficult to understand, but its basic concepts are:
1. Each part of the information must be packaged with -- [boundary_name] to separate each part of the information, and a -- [boundary_name] to end the process.
2. Each information part must have a content-Disposition: Form-data; name = "", and the name is set to the key of http post ).
3. The declaration area and value area must be separated by two new line symbols (in. net, environment. newline ).
4. binary data can be inserted in the middle, but the binary data must be formatted as a binary string. This operation will be automatically removed by the system when httpwebrequest writes data to the uploaded data using networkstream. Write.
5. To set the data type (Content-Type) of different information segments, you must set it in the Declaration area of the information segment.
Once you understand the data format, you can write a program to generate it:
Public static byte [] buildmultipartpostdata (string boundary, Dictionary <string, string> httppostdata, postfiledata fileuploaddata)
{
Stringbuilder sb = new stringbuilder ();
// Append access token.
SB. appendline ("--" + boundary );
SB. append (environment. newline );
// Append form part.
If (httppostdata! = NULL & httppostdata. Count> 0)
{
Foreach (keyvaluepair <string, string> httppostdataitem in httppostdata)
{
SB. appendline ("--" + boundary );
SB. appendline (string. Format ("content-Disposition: Form-data; name = \" {0} \ "", httppostdataitem. Key ));
SB. append (environment. newline );
SB. appendline (httppostdataitem. value );
}
}
// Handle file upload.
If (fileuploaddata! = NULL)
{
SB. appendline ("--" + boundary );
SB. appendline (string. format ("content-Disposition: Form-data; name = \" {0} \ "; filename = \" {1} \ "", fileuploaddata. name, fileuploaddata. filename ));
SB. appendline (string. Format ("Content-Type: {0}", fileuploaddata. contenttype ));
SB. append (environment. newline );
}
Memorystream MS = new memorystream ();
Binarywriter BW = new binarywriter (MS );
Bw. Write (encoding. Default. getbytes (sb. tostring ()));
Bw. Write (fileuploaddata. filedata );
Bw. Write (encoding. Default. getbytes (environment. newline ));
Bw. Write (encoding. Default. getbytes ("--" + boundary ));
Ms. Flush ();
Ms. Position = 0;
Byte [] result = Ms. toarray ();
Bw. Close ();
Return result;
}
The actually sent program does not need to be modified, but the only thing you need to note is to add the boundary parameter, otherwise the ability of multiple information parts will not be available.
Public static string makehttppost (string requesturl, Dictionary <string, string> httppostdata, postfiledata fileuploaddata)
{
Httpwebrequest request = webrequest. Create (requesturl) as httpwebrequest;
Httpwebresponse response = NULL;
Streamreader sr = NULL;
String boundary = "fbgraphapiclient" + datetime. Now. ticks. tostring ();
Try
{
Request. method = "Post ";
Request. contenttype = "multipart/form-data; boundary =" + boundary;
Byte [] multipartpostdata = helpers. buildmultipartpostdata (boundary, httppostdata, fileuploaddata );
Binarywriter BW = new binarywriter (request. getrequeststream ());
Bw. Write (multipartpostdata );
Bw. Close ();
Response = request. getresponse () as httpwebresponse;
Sr = new streamreader (response. getresponsestream ());
String responsedata = Sr. readtoend ();
Sr. Close ();
Response. Close ();
Return responsedata;
}
Catch (webexception we)
{
Throw new apiexception (We. response as httpwebresponse ));
}
Catch (exception)
{
Throw;
}
}
Reference:
1. RFC 2388
2. http://code.msdn.microsoft.com/ASPNET-Web-API-File-Upload-a8c0fb0d
3. http://stackoverflow.com/questions/12593001/web-api-model-binding-with-multipart-formdata
4. http://lonetechie.com/2012/09/23/web-api-generic-mediatypeformatter-for-file-upload/
5. http://www.cnblogs.com/hun_dan/archive/2012/04/09/2438709.html