[MVC]使用ExtJS + ASP.NET MVC做個簡單的File Browser
前言
前陣子看到「ExtJS: Simple File Browser」download來玩一下,它搭配的是php,所以就把它改用ASP.NET MVC,也分享給大家!
實作
JS的部份因為改用ASP.NET MVC,所以要改它url的地方! 另外我要讓它全螢幕,所以改用Viewport來呈現! 也增加Download File的功能! 以下一步一步來說明,
1.建立ASP.NET MVC3專案
2.選擇空白的專案
3.將「ExtJS: Simple File Browser」Download下來的檔案(ext4的目錄),Copy到專案Scripts的目錄之下!
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,如下,
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 ,如下,
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_V1.1.rar (2012/05/18 V1.1 加入不顯示系統及隱藏目錄及檔案!)
Hi,
亂馬客Blog已移到了 「亂馬客 : Re:從零開始的軟體開發生活」
請大家繼續支持 ^_^

