該示例中實際上應用了 jquery ajax(web client) + async web api 雙異步。jquery
jquery ajax postweb
1 $.ajax({ 2 type: "POST", 3 url: "/api/FileUpload", 4 contentType: false, 5 processData: false, 6 data: data, 7 success: function (results) { 8 ShowUploadControls(); 9 $("#uploadResults").empty(); 10 for (i = 0; i < results.length; i++) { 11 $("#uploadResults").append($("<li/>").text(results[i])); 12 } 13 }, 14 error: function (xhr, ajaxOptions, thrownError) { 15 ShowUploadControls(); 16 alert(xhr.responseText); 17 } 18 });
client端以post的方式發送數據。其中上傳成功後的回調腳本定義在success處。ajax
async Web APIapi
Controller處Action返回值爲Task<TResult>,本例中以下定義:app
1 public Task<IEnumerable<string>> Post() 2 { 3 ... ... 4 }
而具體異步效果體如今「文件內容讀取」和「後續處理」上。異步
1 string fullPath = HttpContext.Current.Server.MapPath("~/Uploads"); 2 CustomMultipartFormDataStreamProvider streamProvider = new CustomMultipartFormDataStreamProvider(fullPath); 3 var task = Request.Content.ReadAsMultipartAsync(streamProvider).ContinueWith(t => 4 { 5 if (t.IsFaulted || t.IsCanceled) 6 throw new HttpResponseException(HttpStatusCode.InternalServerError); 7 8 var fileInfo = streamProvider.FileData.Select(i => 9 { 10 var info = new FileInfo(i.LocalFileName); 11 return "File saved as " + info.FullName + " (" + info.Length + ")"; 12 }); 13 return fileInfo; 14 15 });
ReadAsMultipartAsyncasync
(From MSDN) 讀取 MIME 多部分消息中的全部正文部分,並經過使用 streamProvider 實例肯定每一個正文部份內容的寫入位置,來生成一組 HttpContent 實例做爲結果。ide
Task.ContinueWith<TResult>post
建立一個在目標 Task 完成時異步執行的延續任務。具體到該示例中,當 ReadAsMultipartAsync(讀取)任務完成後,ContinueWith 中定義的行爲纔會做爲延續而異步執行。url
MultipartFormDataStreamProvider 對象
一個 IMultipartStreamProvider,適合與 HTML 文件上載一塊兒使用,以將文件內容寫入 FileStream。流提供程序將查看 <b>Content-Disposition</b> 標頭字段,並根據 <b>filename</b> 參數是否存在來肯定輸出 Stream。若是 <b>Content-Disposition</b> 標頭字段中存在 <b>filename</b> 參數,則正文部分將寫入 FileStream 中;不然,正文部分將寫入 MemoryStream 中。這將更加便於處理做爲窗體數據和文件內容的組合的 MIME 多部分 HTML 窗體數據。
小技巧:lambda 表達式反轉,從FileData到IEnumerable<string>
1 var fileInfo = streamProvider.FileData.Select(i => 2 { 3 var info = new FileInfo(i.LocalFileName); 4 return "File saved as " + info.FullName + " (" + info.Length + ")"; 5 });