2012年1月30日 星期一

ASP.NET MVC上傳檔案,使用file-uploader : 基本操作


網站專案大都會使用到上傳檔案的功能,而一般我們大多是直接使用form以及type為file的input element來完成,

例如:

@using (Html.BeginForm("UploadFile", "Home", FormMethod.Post, new { id="FormUpload", enctype = "multipart/form-data" }))
{
    <p>
        Upload File:<input type="file" id="uploadFile" name="uploadFile" size="23" />
        <input type="button" id="ButtonUpload" value="Upload file" />
    </p>
}

這樣的作法是最基本也是最標準的作法,

但是這樣的作法在每次送出檔案上傳到server端後,整個網頁都會Reoload,

於是網路上就有很多AJAX的上傳檔案套件可以讓我們來使用,

而這邊將會以一系列的文章來介紹如何在ASP.NET MVC的環境下使用「file-uploader」這個套件來製作檔案上傳的功能,



valums/file-uploader

 

Ajax Upload; A file upload script with progress-bar, drag-and-drop.

網站:http://valums.com/ajax-upload/

GitHub repository:https://github.com/valums/file-uploader

Download:http://github.com/valums/file-uploader/zipball/master

Wiki:https://github.com/valums/file-uploader/wiki

功能
  • multiple file select, progress-bar in FF, Chrome, Safari
  • drag-and-drop file select in FF, Chrome
  • uploads are cancellable
  • no external dependencies
  • doesn't use Flash
  • fully working with https
  • keyboard support in FF, Chrome, Safari
  • tested in IE7,8; Firefox 3,3.6,4; Safari4,5; Chrome; Opera10.60;

     

    「valums/file-uploader」是個相當容易使用的上傳檔案套件,不需要太繁複設定就可以在套用後就馬上執行功能,

    特色說明:

    1.支援選擇多檔案的上傳(IE, Firefox, Chrome正常而Safari以及Opera無法支援選擇多個檔案)

    image

    2.在Firefox以及Chrome(同屬Webkit的Safari亦同)支援拖曳檔案上傳

    image



    基本使用

    首先從「Download」連結的下載壓縮檔(valums-file-uploader-b3b20b1.zip)

    壓縮檔中的「client」目錄中有以下幾個demo檔案:

    image

    我們要的只有三個檔案:fileuploader.css, fileupload.js, loading.gif,

    將這三個檔案都加入到網站專案中,fileupload.js放到Scripts目錄,其他兩個放到Content目錄中,

    image

     

    前端:View頁面

    在View Page上面放置以下的HTML內容,

    <div id="file-uploader">
        <noscript>
            <p>
                Please enable JavaScript to use file uploader.</p>
            <!-- or put a simple form for upload here -->
        </noscript>
    </div>

    記得頁面上要引用fileupload.css以及fileupload.js

    <link href="@Url.Content("~/Content/fileuploader.css")" rel="stylesheet" type="text/css" />
     
    <script src="@Url.Content("~/Scripts/fileuploader.js")" type="text/javascript"></script>

    接著就是在頁面上使用javascript程式來建立檔案上傳的container element

    <script type="text/javascript" language="javascript">
    <!--
        $(document).ready(function ()
        {
            createUploader();
        });
     
        function createUploader()
        {
            var uploader = new qq.FileUploader(
            {
                element: $('#file-uploader')[0],
                action: '@Url.Action("BasicUpload", "Home")',
            });
        }
    -->
    </script>

    這邊注意到,uploader中的element一定要使用DOM,所以用jQuery selector所選到的元素要轉為DOM node,

    或是說也可以直接用javascript的語法來取得DOM node,

    element: document.getElementById('file-uploader'),

     

    後端:Controller

    傳入BasicUpload方法的參數名稱都是固定使用「qqfile」,

    如果覺得這個名稱不好而想要改的話,就必須連同「fileuploader.js」內也一併做修改,

    所以沒有特殊的需求的話,就還是別去改它。

    後端處理檔案上傳的程式如下:

    public ActionResult BasicUpload(string qqfile)
    
    {
    
        string uploadFolder = "FileUpload";
    
        string path = Server.MapPath(string.Format("~/{0}", uploadFolder));
    
        
    
        try
    
        {
    
            // To handle differences in FireFox/Chrome/Safari/Opera
    
            Stream stream = Request.Files.Count > 0 
    
                ? Request.Files[0].InputStream 
    
                : Request.InputStream;
    
            string filePath = Request.Files.Count > 0
    
                ? Path.Combine(path, System.IO.Path.GetFileName(Request.Files[0].FileName))
    
                : Path.Combine(path, qqfile);
    
            var buffer = new byte[stream.Length];
    
            stream.Read(buffer, 0, buffer.Length);
    
            System.IO.File.WriteAllBytes(filePath, buffer);
    
            return Json(new { success = true }, "text/html");
    
        }
    
        catch (Exception ex)
    
        {
    
            return Json(new { error = ex.Message }, "text/html");
    
        }
    
    }

    因為瀏覽器的不同也讓後端的處理也有所不同(基本上就是分成兩種,一種是IE用而另一個就是非IE),

    IE瀏覽器的上傳,參數「qqfile」是沒有傳入資料的,也取不到「Request.InputStream」,

    而是必須要從「Request.Files[0]」去取得HttpPostedFileBase類別的物件,再從中取得InputStream以及檔案名稱。

    非IE瀏覽器的上傳,可以直接取得「Request.InputStream」並且可以直接取得「qqfile」內容。

    然後再將上傳的位元組陣列寫入到指定目錄路徑的檔案。

     

    而最後不管上傳成功與否,傳回到前端的資料格式雖然是「json」,但是 contentType必須是「text/html」,

    上傳成功:

    {"success":true} 

    上傳失敗:

    {"error":"要顯示的錯誤訊息"} 

     

    如果不是傳回text/html的json資料,IE, Opera瀏覽器是會有以下的情況發生:

    image

    You should return json as a text/html, 
    and escape all '<' as '&lt;', '>' as '&gt;', and '&' as '&amp;'.



    有關於「valums/fi;e-uploader」的基本操作就說明到這裡,而下一篇會再說明進階的使用方式,

    例如:

    • 關閉多選檔案的選項
    • 自定上傳檔案區塊的文字、上傳檔案清單的文字
    • 限制檔案的上傳大小
    • 限制上傳檔案的種類
    • 上傳時也同時上傳其他參數資料
    • 上傳時、上傳完成時的事件處理

    …etc

     

    其他連結:

    Asp.net mvc使用 Ajax Upload上传文件
    http://www.cnblogs.com/bombw/archive/2011/11/02/2232661.html

     

    以上


    沒有留言:

    張貼留言

    提醒

    千萬不要使用 Google Talk (Hangouts) 或 Facebook 及時通訊與我聯繫、提問,因為會掉訊息甚至我是過了好幾天之後才發現到你曾經傳給我訊息過,請多多使用「詢問與建議」(在左邊,就在左邊),另外比較深入的問題討論,或是有牽涉到你實作程式碼的內容,不適合在留言板裡留言討論,請務必使用「詢問與建議」功能(可以夾帶檔案),謝謝。