一般 ASP.NET MVC 4 上傳檔案可以參考:ASP.NET MVC - 檔案上傳的基本操作,而使用 ASP.NET MVC 4 WebApi 結合 Extjs 上傳檔案,可以參考以下做法:
View
使用 Extjs 建立一個 file 欄位 ( 備註:allowBlank : false 為必填 ){ xtype: 'filefield', name: 'photo', fieldLabel: 'Photo', labelWidth: 100, msgTarget: 'side', allowBlank: false, anchor: '100%', buttonText: 'Select Photo...' }
畫面如下:
Button
建立一個按鈕對應 Api 來上傳檔案:buttons: [{ text: 'Send', // button 按下動作 handler: function () { // 檢查 form isValid 檢查條件是否符合 加if 成為判斷式 this.up('form').getForm().isValid(); // 傳送檔案 this.up('form').getForm().submit({ // 傳送到 url url: 'http://localhost/api/Upload', waitMsg: 'Uploading your photo...', success: function (fp, o) { Ext.Msg.alert('Success', 'Your photo "' + o.result.file + '" has been uploaded.'); } }); } }, { text: 'Cancel' }]
Fakepath 解決方案
當開始測試上傳時,發現檔案上傳路徑都不是真實路徑,而會是 C:\fakepath\ 開頭的路徑,實際找尋這個路徑,發現根本不存在。問題來了,現在幾乎每個瀏覽器都會將實際路徑隱藏,這是為了安全性著想,所以將實際路徑以 C:\fakepath\ 取代。
這個問題,其實本是用戶端安全性上考量不提供實際路徑,所以沒有辦法找到檔案上傳,但是,我們不能把這些問題都推給用戶去處理,因為他或許不知道問題在哪,而是我們程式人員必須要解決這問題。
後來發現,在 Controller 可以解決這個問題。
Controller
在 Request.Content 內,可以使用 Request.Content.IsMimeMultipartContent() 判斷是否 MIME 多組件內容,再將 Multipart 內檔案讀到 MemoryStream,最後轉型成 Byte[],再存成實體檔案。[HttpPost] public HttpResponseMessage Post() { if (Request.Content.IsMimeMultipartContent()) { var streamProvider = new MultipartMemoryStreamProvider(); Request.Content.ReadAsMultipartAsync(streamProvider).ContinueWith(t => { foreach (var item in streamProvider.Contents) { if (item.Headers.ContentDisposition.FileName == null) { // 參數區 } else { System.IO.Stream stream = item.ReadAsStreamAsync().Result; byte[] bytes = new byte[stream.Length]; stream.Read(bytes, 0, bytes.Length); System.IO.File.WriteAllBytes(@"D:\Image\" + item.Headers.ContentDisposition.FileName.Replace(@"""", @""), bytes); } } }); } return Request.CreateResponse(HttpStatusCode.OK); }
所以這不管是在是否有實際路徑的情況下都能適用,用戶端不管是否停用或啟用安全性,都會透過 Multipart 傳送檔案到 MemoryStream,在 Controller 讀取這些檔案並且存成實體檔案。
沒有留言 :
張貼留言