2014年2月7日 星期五

ASP.NET MVC 4 WebApi 與 Extjs 的結合 -- 上傳檔案 ( FileUpload )

檔案上傳在 ASP.NET Web Form 中其實只要拉控制項就好,甚至可以做很美觀的介面顯得更友善。

一般 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 讀取這些檔案並且存成實體檔案。


沒有留言 :

張貼留言

Related Posts Plugin for WordPress, Blogger...