[MVC]使用ExtJS + ASP.NET MVC做個簡單的File Browser

[MVC]使用ExtJS + ASP.NET MVC做個簡單的File Browser

前言

前陣子看到「ExtJS: Simple File Browser」download來玩一下,它搭配的是php,所以就把它改用ASP.NET MVC,也分享給大家!

實作

image

JS的部份因為改用ASP.NET MVC,所以要改它url的地方! 另外我要讓它全螢幕,所以改用Viewport來呈現! 也增加Download File的功能! 以下一步一步來說明,

1.建立ASP.NET MVC3專案

1CreateMVC

 

2.選擇空白的專案

2SelectEmpty

 

3.將「ExtJS: Simple File Browser」Download下來的檔案(ext4的目錄),Copy到專案Scripts的目錄之下!

image

 

4.修改Views/Shared/_Layout.cshtml,改加入ExtJS的js及css,如下,

<!DOCTYPE html>
<html>
<head>
    <title>@ViewBag.Title</title>
    <link rel="stylesheet" href="@Url.Content("~/Scripts/ext4/resources/css/ext-all.css")"/>
    <script src="@Url.Content("~/Scripts/ext4/ext-all.js")" type="text/javascript"></script>
    @RenderSection("scripts", false)
    <script type="text/javascript">
        var AP_ROOT = '@Url.Content("~/")';
    </script>
</head>

		
<body>
    @RenderBody()
</body>
</html>

 

 

 

 

5.目前這版是從某個目錄開始瀏覽,所以在web.config appSettings中建立FolderRoot,記錄要瀏覽的根目錄,如下,

<add key="FolderRoot" value="f:\" />

 

 

 

 

6.因為需要「檔案目錄」、「檔案」等資訊,所以在Models中加入FileDir、FileInf及FileToolKits做為記錄檔案資訊之用,如下,

FileDir.cs

using System.Collections.Generic;

		
namespace FileBrowser.Models
{
    /// <summary>
    /// 記錄目錄的資訊
    /// </summary>
    public class FileDir
    {
        public string id { get; set; }

		
        public string text { get; set; }

		
        public bool leaf { get; set; }

		
        public List<FileDir> children { get; set; } 
    }
}

 

FileInf.cs

namespace FileBrowser.Models
{
    /// <summary>
    /// 記錄檔案的資訊
    /// </summary>
    public class FileInf
    {
        public string id { get; set; }

        public string filename { get; set; }

        public string filesize { get; set; }

        public string filedate { get; set; }
    }
}

 

FileToolKits.cs

using System.Collections.Generic;
using System.IO;

		
namespace FileBrowser.Models
{
    public class FileToolKits
    {
        private static string rootPath = 
            System.Configuration.ConfigurationManager.AppSettings["FolderRoot"];
        /// <summary>
        /// 取得web.config設定目錄下的所有目錄
        /// </summary>
        /// <returns></returns>
        public static FileDir GetDirs()
        {
            System.IO.DirectoryInfo root = new System.IO.DirectoryInfo(rootPath); 
            FileDir rootFileDir = new FileDir();
            rootFileDir.text = root.Name;
            rootFileDir.id = rootPath;
            rootFileDir.children = new List<FileDir>();
            SearchFileFolders(ref rootFileDir);

		
            FileDir rootDot = new FileDir();
            rootDot.text = "root";
            rootDot.id = "root";
            rootDot.children = new List<FileDir>();
            rootDot.children.Add(rootFileDir);
            return rootDot;
        }

		
        /// <summary>
        /// 依傳入的目錄,往下找目錄
        /// </summary>
        /// <param name="parentFileDir"></param>
        public static void SearchFileFolders(ref FileDir parentFileDir){
            System.IO.DirectoryInfo parentDir = new System.IO.DirectoryInfo(parentFileDir.id); 
            DirectoryInfo[] dirs  = parentDir.GetDirectories();
            parentFileDir.leaf = (dirs.Length==0);
            foreach (DirectoryInfo dir in dirs)
            {
                FileDir subFileDir = new FileDir();
                subFileDir.text = dir.Name;
                subFileDir.id = Path.Combine(parentFileDir.id, dir.Name);
                subFileDir.children = new List<FileDir>();
                parentFileDir.children.Add(subFileDir);
                SearchFileFolders(ref subFileDir);
            }
        }

		
        /// <summary>
        /// 取得目錄中的檔案
        /// </summary>
        /// <param name="folderPath"></param>
        /// <returns></returns>
        public static List<FileInf> GetFilesByFolderName(string folderPath)
        {
            if (string.IsNullOrEmpty(folderPath))
                folderPath = rootPath;
            List<FileInf> files = new List<FileInf>();
            foreach (FileInfo f in new DirectoryInfo(folderPath).GetFiles())
            {
                FileInf fi = new FileInf();
                fi.id = f.FullName; //Path.Combine(folderPath, f.Name);
                fi.filename = f.Name;
                fi.filedate = f.LastWriteTime.ToString("yyyy/MM/dd HH:mm:ss");
                fi.filesize = GetFileSizeString(f.Length);
                files.Add(fi);
            }
            return files;
        }
        
        /// <summary>
        /// 依檔案Size大小Format
        /// </summary>
        /// <param name="fileSize"></param>
        /// <returns></returns>
        public static string GetFileSizeString(double fileSize)
        {
            string[] sizes = { "B", "KB", "MB", "GB" };
            double len = fileSize;
            int order = 0;
            while (len >= 1024 && order + 1 < sizes.Length)
            {
                order++;
                len = len / 1024;
            }
            return string.Format("{0:0.##} {1}", len, sizes[order]);
        }
    }
}

 

 

 

 

7.新增Home Controller,並建立GetDirs、GetFiles及DownloadFile等3個Action,如下,

AddHomeController

HomeController.cs

using System;
using System.Collections.Generic;
using System.Web;
using System.Web.Mvc;
using FileBrowser.Models;

	
namespace FileBrowser.Controllers
{
    public class HomeController : Controller
    {
        //
        // GET: /Home/
        public ActionResult Index()
        {
            return View();
        }

	
        /// <summary>
        /// 取得web.config設定目錄下的所有目錄
        /// </summary>
        /// <returns></returns>
        public JsonResult GetDirs()
        {
            FileDir rootDirs = FileToolKits.GetDirs();
            return this.Json(rootDirs, JsonRequestBehavior.AllowGet);
        }

	

	
        /// <summary>
        /// 取得目錄中的檔案
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public JsonResult GetFiles(string id)
        {
            
            List<FileInf> files = FileToolKits.GetFilesByFolderName(id);
            return this.Json(files, JsonRequestBehavior.AllowGet);
        }

	
        /// <summary>
        /// 傳出檔案
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public ActionResult DownloadFile(string id)
        {
            if (System.IO.File.Exists(id))
            {
                string  strDownLoadFileName   = System.IO.Path.GetFileName(id);
                string mimeType = "application/octet-stream"; //"application/binary"; //
                if (HttpContext.Request.Browser.Browser == "IE")
                {
                    strDownLoadFileName = HttpContext.Server.UrlPathEncode(strDownLoadFileName);
                }
                using (System.IO.FileStream fs = new System.IO.FileStream(id, System.IO.FileMode.Open, 
                    System.IO.FileAccess.Read, System.IO.FileShare.Read))
                {

	
                    // Read the source file into a byte array.
                    byte[] bytes = new byte[fs.Length];
                    int numBytesToRead = (int)fs.Length;
                    int numBytesRead = 0;
                    while (numBytesToRead > 0)
                    {
                        // Read may return anything from 0 to numBytesToRead.
                        int n = fs.Read(bytes, numBytesRead, numBytesToRead);

	
                        // Break when the end of the file is reached.
                        if (n == 0)
                            break;

	
                        numBytesRead += n;
                        numBytesToRead -= n;
                    }
                    numBytesToRead = bytes.Length;

	
                    return File(bytes, mimeType, strDownLoadFileName);
                }
             }
            return null;
        }

	
    }

	

}

 

 

 

 

8.新增Home Controller Index Action的View,並勾選「使用配置或主版頁面(U)」為 ~/Views/Shared/_Layout.cshtml ,如下,

AddIndexView

 

9.將「ExtJS: Simple File Browser」範例的JS,Copy到View Index.cshtml之中,並調整它!

Index.cshtml

@{
    ViewBag.Title = "Index";
    Layout = "~/Views/Shared/_Layout.cshtml";
}
@section scripts
{
    <script type="text/javascript">
        Ext.onReady(function () {
            store_dir = Ext.create('Ext.data.TreeStore', {
                proxy: {
                    type: 'ajax',
                    url: '@Url.Content("~/Home/GetDirs")'
                }
            });

		
            tree_dir = Ext.create('Ext.tree.Panel', {
                title: 'Localhost Directory',
                rootVisible: false,
                store: store_dir,
                split: true,
                region: 'west',
                collapsible: true,
                floatable: false,
                width: 400,
                useArrows: true,
                listeners: {
                    itemclick: {
                        fn: function (view, record, item, index, event) {
                            store_file.load({
                                url: '@Url.Content("~/Home/GetFiles?id=")'
                                    + encodeURI(record.data.id)
                            });
                            nodeId = record.data.Name;
                            htmlId = item.id;
                        }
                    }

		
                }
            });

		
            Ext.define('File', {
                extend: 'Ext.data.Model',
                fields: ['id', 'filename', 'filesize', 'filedate']
            });

		
            store_file = Ext.create('Ext.data.Store', {
                model: 'File',
                proxy: {
                    type: 'ajax',
                    url: 'GetFiles',
                    reader: {
                        type: 'json',
                        root: 'files'
                    }
                }
            });

		
            grid_file = Ext.create('Ext.grid.Panel', {
                title: 'File List',
                region: 'center',
                store: store_file,
                columns: [
                { header: 'Name', width: 200, dataIndex: 'filename', flex: 1, tdCls: 'file-column' },
                { header: 'Size', width: 100, dataIndex: 'filesize', align: 'right' },
                { header: 'Last Modified', width: 150, dataIndex: 'filedate' }
                ],
                viewConfig: {
                    stripeRows: true
                },
                listeners: {
                    itemclick: {
                        fn: function (view, record, item, index, event) {
                            Ext.getDom("downloadIframe").src = '@Url.Content("~/Home/DownloadFile/?id=")'
                                + encodeURI(record.data.id);
                        }
                    }

		
                }
            });

		
            var viewport = new Ext.Viewport({
                layout: 'border',
                bodyStyle: 'padding: 5px;',
                items: [tree_dir, grid_file],
                renderTo: Ext.getBody()
            });
        });
         
    </script>
}
<iframe id="downloadIframe" src="javascript:''" style="display: none"></iframe>

 

結論

使用ExtJS這類的JS Framework很多元件都幫我們包的好好的,運作上方便了許多。
以上只是簡單的功能,希望未來能再加入更多的功能跟大家分享。

 

註:ExtJS相關資訊請參考:http://www.sencha.com/products/extjs/

原始碼 :

FileBrowser.rar

FileBrowser_V1.1.rar  (2012/05/18 V1.1 加入不顯示系統及隱藏目錄及檔案!)

Hi, 

亂馬客Blog已移到了 「亂馬客​ : Re:從零開始的軟體開發生活

請大家繼續支持 ^_^