[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:從零開始的軟體開發生活」
請大家繼續支持 ^_^