標籤:des blog http io ar os 使用 sp for
5.3 Sending HTML Form Data
5.3 發送HTML表單資料(2)
本文引自:http://www.cnblogs.com/r01cn/archive/2012/12/20/2826230.html
By Mike Wasson|June 21, 2012
Mike Wasson | 日期:2012-6-21
Part 2: File Upload and Multipart MIME
第2部分:檔案上傳與多部分MIME
This tutorial shows how to upload files to a web API. It also describes how to process multipart MIME data.
本教程示範如何對Web API上傳檔案。也描述如何處理多部分MIME資料。
Download the completed project.
下載完整的項目。
Here is an example of an HTML form for uploading a file:
以下是一個上傳檔案的HTML表單(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>
圖5-8. 檔案上傳表單
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 will be sent as a multipart MIME message.
該表單有一個文本輸入控制項和一個檔案輸入控制項。當表單含有檔案輸入控制項時,其enctype標籤屬性應當總是“multipart/form-data”,它指示此表單將作為多部分MIME訊息進行發送。
The format of a multipart MIME message is easiest to understand by looking at an example request:
通過考察一個樣本請求,很容易理解multipart(多部分)MIME訊息的格式:
POST http://localhost:50460/api/values/1 HTTP/1.1User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:12.0) Gecko/20100101 Firefox/12.0Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8Accept-Language: en-us,en;q=0.5Accept-Encoding: gzip, deflateContent-Type: multipart/form-data; boundary=---------------------------41184676334Content-Length: 29278
-----------------------------41184676334Content-Disposition: form-data; name="caption"
Summer vacation-----------------------------41184676334Content-Disposition: form-data; name="image1"; filename="GrandCanyon.jpg"Content-Type: image/jpeg
(Binary data not shown)(位元據,未列出)-----------------------------41184676334--
This message is divided into two parts, one for each form control. Part boundaries are indicated by the lines that start with dashes.
這條訊息分成兩個組件(parts),分別用於每個表單控制項。組件邊界由以一些破折號開始的行指示。
The part boundary includes a random component ("41184676334") to ensure that the boundary string does not accidentally appear inside a message part.
組件邊界包含了一個隨機組件(“41184676334”),以確保邊界字串不會偶然出現在訊息組件之中。
Each message part contains one or more headers, followed by the part contents.
每一個訊息組件含有一個或多個前序,後跟組件內容。
- The Content-Disposition header includes the name of the control. For files, it also contains the file name.
Content-Disposition(內容布置)前序包括控制項名稱。對於檔案,它也包括檔案名稱。
- The Content-Type header describes the data in the part. If this header is omitted, the default is text/plain.
Content-Type(內容類型)前序描述組件中的資料。如果該前序被忽略,預設為text/plain(文字格式設定)。
In the previous example, the user uploaded a file named GrandCanyon.jpg, with content type image/jpeg; and the value of the text input was "Summer Vacation".
在上一樣本中,使用者上傳名為GrandCanyon.jpg的檔案,其內容類型為image/jpeg,而文本輸入框的值為“Summer Vacation”。
File Upload
檔案上傳
Now let‘s look at a Web API controller that reads files from a multipart MIME message. The controller will read the files asynchronously. Web API supports asynchronous actions using the task-based programming model. First, here is the code if you are targeting .NET Framework 4.5, which supports the async and await keywords.
現在,讓我們考查從一個多部分MIME訊息讀取檔案的控制器。該控制器將非同步讀取檔案。Web API支援使用“基於任務的編程模型(這是關於.NET並行編程的MSDN文檔 — 譯者注)”的非同步動作。首先,以下是針對.NET Framework 4.5的代碼,它支援async和await關鍵字。
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. // 檢查該請求是否含有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. // 讀取表單資料 await Request.Content.ReadAsMultipartAsync(provider);
// This illustrates how to get the file names. // 以下描述如何擷取檔案名稱 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.
注意,控制器動作不取任何參數。這是因為我們是在動作中處理請求體的,不必調用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).
IsMultipartContent方法檢查該請求是否含有多部分MIME訊息。如果不是,控制器返回HTTP狀態代碼415(不支援的媒體類型)。
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.
MultipartFormDataStreamProvider類是一個輔助器對象,它為上傳檔案分配檔案流。為了讀取多部分MIME訊息,需調用ReadAsMultipartAsync方法。該方法提取所有訊息組件,並把它們寫入由MultipartFormDataStreamProvider提供的流中。
When the method completes, you can get information about the files from the FileData property, which is a collection of MultipartFileDataobjects.
當該方法完成時,你可以通過FileData屬性獲得檔案的資訊,該屬性是一個MultipartFileData對象的集合。
- MultipartFileData.FileName is the local file name on the server, where the file was saved.
MultipartFileData.FileName是儲存此檔案的伺服器上的一個本地檔案名稱。
- 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含有組件前序(不是請求前序)。你可以用它來訪問Content_Disposition和Content-Type前序。
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).
正如名稱所暗示的那樣,ReadAsMultipartAsync是一個非同步方法呼叫。為了在該方法完成之後執行一些工作,需要使用“continuation(繼續)任務”(.NET 4.0)或await關鍵字(.NET 4.5)。
Here is the .NET Framework 4.0 version of the previous code:
以下是前述代碼的.NET Framework 4.0版本:
public Task<HttpResponseMessage> PostFormData(){ // Check if the request contains multipart/form-data. // 檢查該請求是否含有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. // 讀取表單資料,並返回一個async任務 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. // 以下描述了如何擷取檔案名稱 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
讀取表單控制項資料
The HTML form that I showed earlier had a text input control.
前面顯示的HTML表單有一個文本輸入控制項。
<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.
可以通過MultipartFormDataStreamProvider的FormData屬性擷取控制項的值。
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. // 顯示所有“鍵-值”對 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是一個NameValueCollection(名字/值集合),它含有表單控制項的“名字/值”對。該集合可能含有重複鍵。考慮以下表單(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>
圖5-9. 有重複鍵的表單
The request body might look like this:
該請求體看上去可能像這樣:
-----------------------------7dc1d13623304d6Content-Disposition: form-data; name="trip"
round-trip-----------------------------7dc1d13623304d6Content-Disposition: form-data; name="options"
nonstop-----------------------------7dc1d13623304d6Content-Disposition: form-data; name="options"
dates-----------------------------7dc1d13623304d6Content-Disposition: form-data; name="seat"
window-----------------------------7dc1d13623304d6--
In that case, the FormData collection would contain the following key/value pairs:
在這種情況下,FormData集合會含有以下“鍵/值”對:
- trip: round-trip
- options: nonstop
- options: dates
- seat: window
(轉)WebApi發送HTML表單資料:檔案上傳與多部分MIME