5.3 Sending HTML Form Data
5.3 Sending HTML form data (2)
This article quoted: http://www.cnblogs.com/r01cn/archive/2012/12/20/2826230.html
by Mike wasson| June 21, 2012
Mike Wasson | date: 2012-6-21
Part 2:file Upload and Multipart MIME
Part 2nd: File uploads and multipart MIME
This tutorial shows how to upload files to a Web API. It also describes how to process multipart MIME data.
This tutorial shows how to upload a file to the Web API. It also describes how to handle multipart MIME data.
Download the completed project.
Download the full project.
Example of an HTML form for uploading a file:
The following is an HTML form for uploading a file (5-8):
<form name="form1" method="post" enctype="multipart/form-data" action="api/upload">
<div>
<label for="caption">Image Caption</label>
<input name="caption" type="text" />
</div>
<div>
<label for="image1">Image File</label>
<input name="image1" type="file" />
</div>
<div>
<input type="submit" value="Submit" />
</div>
</form>
Figure 5-8. File Upload Form
This form contains a text input control and a file input control. When a form contains a file input control, the enctype attribute should always be "multipart/form-data", which Specifies that the form would be sent as a multipart MIME message.
This form has a text input control and a file input control. When a form contains a file input control, its enctype Tag property should always be "multipart/form-data", which indicates that the form will be sent as a multipart MIME message.
The format of a multipart MIME message is easiest to understand by looking at an example request:
By examining a sample request, it is easy to understand the format of the multipart (multipart) MIME message:
POST http: // localhost: 50460 / api / values / 1 HTTP / 1.1
User-Agent: Mozilla / 5.0 (Windows NT 6.1; WOW64; rv: 12.0) Gecko / 20100101 Firefox / 12.0
Accept: text / html, application / xhtml + xml, application / xml; q = 0.9, * / *; q = 0.8
Accept-Language: en-us, en; q = 0.5
Accept-Encoding: gzip, deflate
Content-Type: multipart / form-data; boundary = --------------------------- 41184676334
Content-Length: 29278
----------------------------- 41184676334
Content-Disposition: form-data; name = "caption"
Summer vacation
----------------------------- 41184676334
Content-Disposition: form-data; name = "image1"; filename = "GrandCanyon.jpg"
Content-Type: image / jpeg
(Binary data not shown)
----------------------------- 41184676334--
This message was divided into the parts, one for each form control. Part boundaries is indicated by the lines so start with dashes.
This message is divided into two parts (parts) for each form control. The part boundary is indicated by a line that starts with some dashes.
The part boundary includes a random component ("41184676334") to ensure, the boundary string does not accidentally app Ear inside a message part.
The part boundary contains a random component ("41184676334") to ensure that the boundary string does not accidentally appear in the message part.
Each message part contains one or more headers, followed by the part contents.
Each message part contains one or more headers followed by the contents of the part.
- The content-disposition header includes the name of the control. For files, it also contains the file name.
The Content-disposition (Content layout) header includes the control name. For a file, it also includes the file name.
- The Content-type header describes the data in the part. If the header is omitted, the default is Text/plain.
The Content-type (content Type) header describes the data in the part. If the header is ignored, the default is Text/plain (text format).
The previous example, the user uploaded a file named Grandcanyon.jpg, with content type image/jpeg; The value of the text input was "Summer Vacation".
In the previous example, the user uploads a file named Grandcanyon.jpg, whose content type is image/jpeg, and the text input box has a value of "Summer Vacation".
File Upload
File Upload
Now let's look at a WEB API controller this reads files from a multipart MIME message. The controller would read the files asynchronously. Web API supports asynchronous actions using the Task-based programming model. First, here's the code if you are targeting. NET Framework 4.5, which supports the async and await keyw Ords.
Now let's examine the controller that reads the file from a multi-part MIME message. The controller will read the file asynchronously. The Web API supports the use of the task-based programming model (this is about. NET Parallel Programming MSDN Documentation-Translator note) "for asynchronous actions. First, the following is code for the. NET Framework 4.5, which supports the async and await keywords.
using System.Diagnostics;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using System.Web;
using System.Web.Http;
public class UploadController: ApiController
{
public async Task <HttpResponseMessage> PostFormData ()
{
// Check if the request contains multipart / form-data.
// check if the request contains multipart / form-data
if (! Request.Content.IsMimeMultipartContent ())
{
throw new HttpResponseException (HttpStatusCode.UnsupportedMediaType);
}
string root = HttpContext.Current.Server.MapPath ("~ / App_Data");
var provider = new MultipartFormDataStreamProvider (root);
try
{
// Read the form data.
// read form data
await Request.Content.ReadAsMultipartAsync (provider);
// This illustrates how to get the file names.
// The following describes how to get the file name
foreach (MultipartFileData file in provider.FileData)
{
Trace.WriteLine (file.Headers.ContentDisposition.FileName);
Trace.WriteLine ("Server file path:" + file.LocalFileName);
}
return Request.CreateResponse (HttpStatusCode.OK);
}
catch (System.Exception e)
{
return Request.CreateErrorResponse (HttpStatusCode.InternalServerError, e);
}
}
}
Notice that the controller action does not take any parameters. That ’s because we process the request body inside the action, without invoking a media-type formatter.
Note that the controller action does not take any parameters. This is because we are processing the request body in the action, without having to call the media-type formatter.
The IsMultipartContent method checks whether the request contains a multipart MIME message. If not, the controller returns HTTP status code 415 (Unsupported Media Type).
The IsMultipartContent method checks whether the request contains a multipart MIME message. If not, the controller returns HTTP status code 415 (unsupported media type).
The MultipartFormDataStreamProvider class is a helper object that allocates file streams for uploaded files. To read the multipart MIME message, call the ReadAsMultipartAsync method. This method extracts all of the message parts and writes them into the streams provided by the MultipartFormDataStreamProvider.
The MultipartFormDataStreamProvider class is a helper object that distributes file streams for uploaded files. In order to read a multipart MIME message, the ReadAsMultipartAsync method needs to be called. This method extracts all the message parts and writes them to the stream provided by MultipartFormDataStreamProvider.
When the method completes, you can get information about the files from the FileData property, which is a collection of MultipartFileDataobjects.
When the method is complete, you can get information about the file through the FileData property, which is a collection of MultipartFileData objects.
MultipartFileData.FileName is the local file name on the server, where the file was saved.
MultipartFileData.FileName is a local file name on the server that holds this file.
MultipartFileData.Headers contains the part header (not the request header). You can use this to access the Content_Disposition and Content-Type headers.
MultipartFileData.Headers contains part headers (not request headers). You can use it to access the Content_Disposition and Content-Type headers.
As the name suggests, ReadAsMultipartAsync is an asynchronous method. To perform work after the method completes, use a continuation task (.NET 4.0) or the await keyword (.NET 4.5).
As the name implies, ReadAsMultipartAsync is an asynchronous method. In order to perform some work after this method is completed, you need to use the "continuation task" (.NET 4.0) or the await keyword (.NET 4.5).
Here is the .NET Framework 4.0 version of the previous code:
Here is the .NET Framework 4.0 version of the aforementioned code:
public Task <HttpResponseMessage> PostFormData ()
{
// Check if the request contains multipart / form-data.
// check if the request contains multipart / form-data
if (! Request.Content.IsMimeMultipartContent ())
{
throw new HttpResponseException (HttpStatusCode.UnsupportedMediaType);
}
string root = HttpContext.Current.Server.MapPath ("~ / App_Data");
var provider = new MultipartFormDataStreamProvider (root);
// Read the form data and return an async task.
// read form data and return an async task
var task = Request.Content.ReadAsMultipartAsync (provider).
ContinueWith <HttpResponseMessage> (t =>
{
if (t.IsFaulted || t.IsCanceled)
{
Request.CreateErrorResponse (HttpStatusCode.InternalServerError, t.Exception);
}
// This illustrates how to get the file names.
// The following describes how to get the file name
foreach (MultipartFileData file in provider.FileData)
{
Trace.WriteLine (file.Headers.ContentDisposition.FileName);
Trace.WriteLine ("Server file path:" + file.LocalFileName);
}
return Request.CreateResponse (HttpStatusCode.OK);
});
return task;
}
Reading Form Control Data
Read form control data
The HTML form that I showed earlier had a text input control.
The HTML form shown earlier has a text input control.
<div>
<label for = "caption"> Image Caption </ label>
<input name = "caption" type = "text" />
</ div>
You can get the value of the control from the FormData property of the MultipartFormDataStreamProvider.
You can get the value of the control through the FormData property of the MultipartFormDataStreamProvider.
public async Task <HttpResponseMessage> PostFormData ()
{
if (! Request.Content.IsMimeMultipartContent ())
{
throw new HttpResponseException (HttpStatusCode.UnsupportedMediaType);
}
string root = HttpContext.Current.Server.MapPath ("~ / App_Data");
var provider = new MultipartFormDataStreamProvider (root);
try
{
await Request.Content.ReadAsMultipartAsync (provider);
// Show all the key-value pairs.
// show all "key-value" pairs
foreach (var key in provider.FormData.AllKeys)
{
foreach (var val in provider.FormData.GetValues (key))
{
Trace.WriteLine (string.Format ("{0}: {1}", key, val));
}
}
return Request.CreateResponse (HttpStatusCode.OK);
}
catch (System.Exception e)
{
return Request.CreateErrorResponse (HttpStatusCode.InternalServerError, e);
}
}
FormData is a NameValueCollection that contains name / value pairs for the form controls. The collection can contain duplicate keys. Consider this form:
FormData is a NameValueCollection, which contains the "name / value" pairs of the form control. The collection may contain duplicate keys. Consider the following form (5-9):
<form name="trip_search" method="post" enctype="multipart/form-data" action="api/upload">
<div>
<input type="radio" name="trip" value="round-trip"/>
Round-Trip
</div>
<div>
<input type="radio" name="trip" value="one-way"/>
One-Way
</div>
<div>
<input type="checkbox" name="options" value="nonstop" />
Only show non-stop flights
</div>
<div>
<input type="checkbox" name="options" value="airports" />
Compare nearby airports
</div>
<div>
<input type="checkbox" name="options" value="dates" />
My travel dates are flexible
</div>
<div>
<label for="seat">Seating Preference</label>
<select name="seat">
<option value="aisle">Aisle</option>
<option value="window">Window</option>
<option value="center">Center</option>
<option value="none">No Preference</option>
</select>
</div>
</form>
The request body might look like this:
-----------------------------7dc1d13623304d6
Content-Disposition: form-data; name="trip"
round-trip
-----------------------------7dc1d13623304d6
Content-Disposition: form-data; name="options"
nonstop
-----------------------------7dc1d13623304d6
Content-Disposition: form-data; name="options"
dates
-----------------------------7dc1d13623304d6
Content-Disposition: form-data; name="seat"
window
-----------------------------7dc1d13623304d6--
In that case, the FormData collection would contain the following key / value pairs:
In this case, the FormData collection will contain the following "key / value" pairs:
trip: round-trip
options: nonstop
options: dates
seat: window
(Transfer) WebApi sends HTML form data: file upload and multipart MIME