ASP.NET MVC 實現頁落網資源分享網站+充值管理+後臺管理(7)之擴充套件基類和區域建立以及文字編輯配置
一、擴充套件基類和區域建立
(1)在應用之前,我們先在表現層建立一個公共的系統擴充套件檔案來(SystemExtension)存放我們需要延伸和擴充套件的方法類。
在常規的專案系統操作中,我們都需要用到增刪查改的基礎操作管理,所以我們可以建一個公共的控制控制器(PublicController)來讓用得到的控制器來繼承,當然如果特殊和複雜的操作,我們在進行方法重寫。
PublicController.cs
using Bobo.DataAccess.DataBase; using Bobo.Repository; using Bobo.Utilities; using IA.Business; using IA.Business.SystemBusiness; using IA.Entity; using System; using System.Collections; using System.Collections.Generic; using System.Data.Common; using System.Diagnostics; using System.Linq; using System.Web; using System.Web.Mvc; namespace IA.WebApp {/// <summary> /// 控制器公共基類 /// 這樣可以減少很多重複程式碼量 /// </summary> /// <typeparam name="TEntity"></typeparam> public class PublicController<TEntity> : Controller where TEntity : BaseEntity, new() { public readonly RepositoryFactory<TEntity> repositoryfactory = new RepositoryFactory<TEntity>(); #region 列表 /// <summary> /// 列表檢視 /// </summary> /// <returns></returns> //[ManagerPermission(PermissionMode.Enforce)] public virtual ActionResult Index() { return View(); } /// <summary> /// 繫結表格 /// </summary> /// <param name="ParameterJson">查詢條件</param> /// <param name="Gridpage">分頁條件</param> /// <returns></returns> //[LoginAuthorize] public virtual JsonResult GridPageJson(string ParameterJson, JqGridParam jqgridparam) { try { Stopwatch watch = CommonHelper.TimerStart(); List<TEntity> ListData = new List<TEntity>(); if (!string.IsNullOrEmpty(ParameterJson)) { List<DbParameter> parameter = new List<DbParameter>(); IList conditions = ParameterJson.JsonToList<Condition>(); string WhereSql = ConditionBuilder.GetWhereSql(conditions, out parameter); ListData = repositoryfactory.Repository().FindListPage(WhereSql, parameter.ToArray(), ref jqgridparam); } else { ListData = repositoryfactory.Repository().FindListPage(ref jqgridparam); } var JsonData = new { total = jqgridparam.total, page = jqgridparam.page, records = jqgridparam.records, costtime = CommonHelper.TimerEnd(watch), rows = ListData, }; return Json(JsonData, JsonRequestBehavior.AllowGet); } catch (Exception ex) { Base_SysLogBll.Instance.WriteLog("", OperationType.Query, "-1", "異常錯誤:" + ex.Message + "\r\n條件:" + ParameterJson); return null; } } /// <summary> /// 繫結表格 /// </summary> /// <param name="ParameterJson">查詢條件</param> /// <param name="Gridpage">排序條件</param> /// <returns></returns> //[LoginAuthorize] public virtual JsonResult GridJson(string ParameterJson, JqGridParam jqgridparam) { try { List<TEntity> ListData = new List<TEntity>(); if (!string.IsNullOrEmpty(ParameterJson)) { List<DbParameter> parameter = new List<DbParameter>(); IList conditions = ParameterJson.JsonToList<Condition>(); string WhereSql = ConditionBuilder.GetWhereSql(conditions, out parameter, jqgridparam.sidx, jqgridparam.sord); ListData = repositoryfactory.Repository().FindList(WhereSql, parameter.ToArray()); } else { ListData = repositoryfactory.Repository().FindList(); } return Json(ListData, JsonRequestBehavior.AllowGet); } catch (Exception ex) { Base_SysLogBll.Instance.WriteLog("", OperationType.Query, "-1", "異常錯誤:" + ex.Message + "\r\n條件:" + ParameterJson); return null; } } /// <summary> /// 查詢列表資料的通用方法 /// </summary> /// <param name="listData">獲取列表資料的方法</param> /// <param name="logMessage">捕獲到異常時,要寫入日誌的資訊,不寫入則傳null</param> /// <returns></returns> protected ActionResult FindPage(Func<JqGridParam, object> listData, Func<Exception, string> logMessage, JqGridParam jqGridParam) { Stopwatch watch = CommonHelper.TimerStart(); try { object datas = listData(jqGridParam); var jsonData = new { total = jqGridParam.total, page = jqGridParam.page, records = jqGridParam.records, costtime = CommonHelper.TimerEnd(watch), rows = datas, }; return Content(jsonData.ToJson()); } catch (Exception ex) { if (logMessage != null) { string message = logMessage(ex); if (message != null) { WriteLog(-1, "", message); } } return null; } } /// <summary> /// 刪除資料 /// </summary> /// <param name="KeyValue">主鍵值</param> /// <param name="ParentId">判斷是否有子節點</param> /// <returns></returns> [HttpPost] //[ManagerPermission(PermissionMode.Enforce)] public virtual ActionResult Delete(string KeyValue, string ParentId) { string[] array = KeyValue.Split(','); try { var Message = "刪除失敗。"; int IsOk = 0; if (!string.IsNullOrEmpty(ParentId)) { if (repositoryfactory.Repository().FindCount("ParentId", ParentId) > 0) { throw new Exception("當前所選有子節點資料,不能刪除。"); } } IsOk = repositoryfactory.Repository().Delete(array); if (IsOk > 0) { Message = "刪除成功。"; } WriteLog(IsOk, array, Message); return Content(new JsonMessage { Success = true, Code = IsOk.ToString(), Message = Message }.ToString()); } catch (Exception ex) { WriteLog(-1, array, "操作失敗:" + ex.Message); return Content(new JsonMessage { Success = false, Code = "-1", Message = "操作失敗:" + ex.Message }.ToString()); } } #endregion #region 表單 /// <summary> /// 明細檢視 /// </summary> /// <returns></returns> //[ManagerPermission(PermissionMode.Enforce)] public virtual ActionResult Detail() { return View(); } /// <summary> /// 表單檢視 /// </summary> /// <returns></returns> //[ManagerPermission(PermissionMode.Enforce)] public virtual ActionResult Form() { return View(); } /// <summary> /// 返回顯示順序號 /// </summary> /// <returns></returns> //[LoginAuthorize] public virtual ActionResult SortCode() { string strCode = BaseFactory.BaseHelper().GetSortCode<TEntity>("SortCode").ToString(); return Content(strCode); } /// <summary> /// 表單賦值 /// </summary> /// <param name="KeyValue">主鍵值</param> /// <returns></returns> [HttpPost] [ValidateInput(false)] //[LoginAuthorize] public virtual ActionResult SetForm(string KeyValue) { TEntity entity = repositoryfactory.Repository().FindEntity(KeyValue); return Content(entity.ToJson()); } /// <summary> /// 提交表單 /// </summary> /// <param name="entity">實體物件</param> /// <param name="KeyValue">主鍵值</param> /// <returns></returns> [HttpPost] [ValidateInput(false)] //[LoginAuthorize] public virtual ActionResult SubmitForm(TEntity entity, string KeyValue) { try { int IsOk = 0; string Message = KeyValue == "" ? "新增成功。" : "編輯成功。"; if (!string.IsNullOrEmpty(KeyValue)) { TEntity Oldentity = repositoryfactory.Repository().FindEntity(KeyValue);//獲取沒更新之前實體物件 entity.Modify(KeyValue); IsOk = repositoryfactory.Repository().Update(entity); this.WriteLog(IsOk, entity, Oldentity, KeyValue, Message); } else { entity.Create(); IsOk = repositoryfactory.Repository().Insert(entity); this.WriteLog(IsOk, entity, null, KeyValue, Message); } return Content(new JsonMessage { Success = true, Code = IsOk.ToString(), Message = Message }.ToString()); } catch (Exception ex) { this.WriteLog(-1, entity, null, KeyValue, "操作失敗:" + ex.Message); return Content(new JsonMessage { Success = false, Code = "-1", Message = "操作失敗:" + ex.Message }.ToString()); } } #endregion #region 寫入作業日誌 /// <summary> /// 寫入作業日誌(新增、修改) /// </summary> /// <param name="IsOk">操作狀態</param> /// <param name="entity">實體物件</param> /// <param name="Oldentity">之前實體物件</param> /// <param name="Message">備註資訊</param> public void WriteLog(int IsOk, TEntity entity, TEntity Oldentity, string KeyValue, string Message = "") { if (!string.IsNullOrEmpty(KeyValue)) { Base_SysLogBll.Instance.WriteLog(Oldentity, entity, OperationType.Update, IsOk.ToString(), Message); } else { Base_SysLogBll.Instance.WriteLog(entity, OperationType.Add, IsOk.ToString(), Message); } } /// <summary> /// 寫入作業日誌(新增、修改)(通殺版) /// </summary> /// <param name="IsOk">操作狀態</param> /// <param name="entity">實體物件</param> /// <param name="Oldentity">之前實體物件</param> /// <param name="Message">備註資訊</param> public void WriteLog<T>(int IsOk, T entity, T Oldentity, string KeyValue, string Message = "") where T : new() { if (!string.IsNullOrEmpty(KeyValue)) { Base_SysLogBll.Instance.WriteLog(Oldentity, entity, OperationType.Update, IsOk.ToString(), Message); } else { Base_SysLogBll.Instance.WriteLog(entity, OperationType.Add, IsOk.ToString(), Message); } } /// <summary> /// 寫入作業日誌(刪除操作) /// </summary> /// <param name="IsOk">操作狀態</param> /// <param name="KeyValue">主鍵值</param> /// <param name="Message">備註資訊</param> public void WriteLog(int IsOk, string[] KeyValue, string Message = "") { Base_SysLogBll.Instance.WriteLog<TEntity>(KeyValue, IsOk.ToString(), Message); } /// <summary> /// 寫入作業日誌(刪除操作) /// </summary> /// <param name="IsOk">操作狀態</param> /// <param name="KeyValue">主鍵值</param> /// <param name="Message">備註資訊</param> public void WriteLog(int IsOk, string KeyValue, string Message = "") { string[] array = KeyValue.Split(','); Base_SysLogBll.Instance.WriteLog<TEntity>(array, IsOk.ToString(), Message); } #endregion } }
(2)區域建立,我們需要建立一個叫BackstageModule的區域,用來存放後臺管理的表現層,在這個區域裡,我們需要更改Area的路由對映:
注意區域裡面對映設定和名稱的對應。
然後我們在表現層(非區域)的Shared檔案中建立MVC佈局頁_LayoutMange.cshtml和_LayoutForm.cshtml,用來供後臺管理頁面和form表單頁面引用:
建立好之後,在佈局檔案中引用功能頁面需要用到(頻率高和共用)的樣式檔案、js檔案等,提供程式碼如下:
_LayoutMange.cshtml
@using Bobo.Utilities @using IA.Business <!DOCTYPE html> <html> @*後臺公共模組*@ <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width" /> <title>@ViewBag.Title</title> <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico" media="screen" /> <link href="~/Content/Styles/main.css" rel="stylesheet" /> <link href="~/Content/Styles/base.css" rel="stylesheet" /> <script src="~/Content/Scripts/datepicker/WdatePicker.js"></script> <script src="~/Content/Scripts/jquery/jquery-1.8.2.min.js"></script> <script src="~/Content/Scripts/jquery.form.js"></script> <script src="~/Content/Scripts/boboui-jshelp.js"></script> <script src="~/Content/Scripts/validator/boboui-validator.js"></script> <script src="~/Content/Scripts/layer/layer.js"></script> <script src="~/Content/Scripts/Juicer/juicer.js"></script> <script src="~/Content/Scripts/m_pager.js"></script> </head> <body class="set_body"> <div class="w_header font-yahei"> <div class="header-item"> <div class="mAuto"> <div class="L">頁落素材網 - 使用者管理後臺 【當前使用者】:admin</div> <div class="R"><a href="javascript:;" id="LoginOut" style="color: #00b7f0;">【退出登入】</a></div> </div> </div> <div class="header-nav clear"> <div class="mAuto"> <a href="/" class="logo L"> <img src="~/Content/Images/slice/logoMange.png" /></a> <ul class="R nav-item"> <li class="L"><a href="/BackstageModule/Article/Index" class="wzgl">網站管理</a></li> <li class="L"><a href="/BackstageModule/TrainSignupInfo/Index" class="hypx">區塊鏈</a></li> <li class="L"><a href="/BackstageModule/MemberManagement/Index" class="hygl">人工智慧</a></li> <li class="L"><a href="/">返回首頁</a></li> </ul> </div> </div> </div> @RenderBody() <div id="footer"> <div class="foot-tip w_footer"> <div class="webPage text-center"> 頁落素材網是網頁特效下載社群,以提高效率、分享經驗的理念,提供高品質實用、簡單、易懂的Web頁面特效。 </div> </div> </div> <script type="text/javascript"> //複選框選定事件 function change(obj) { var tr = obj.parentElement.parentElement; if (obj.checked) { tr.style.backgroundColor = '#e5eaff'; tr.style.borderColor = '#cacccb'; } else { tr.style.backgroundColor = '#fff'; } } </script> @RenderSection("scripts", required: false) </body> </html>
_LayoutForm.cshtml
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width" /> <title>@ViewBag.Title</title> <link href="~/Content/Styles/main.css" rel="stylesheet" /> <link href="~/Content/Styles/base.css" rel="stylesheet" /> <script src="~/Content/Scripts/datepicker/WdatePicker.js"></script> </head> <body> @RenderBody() <script src="~/Content/Scripts/jquery/jquery-1.8.2.min.js"></script> <script src="~/Content/Scripts/jquery.form.js"></script> <script src="~/Content/Scripts/boboui-jshelp.js"></script> <script src="~/Content/Scripts/validator/boboui-validator.js"></script> <script src="~/Content/Scripts/layer/layer.js"></script> <script src="~/Content/Scripts/Juicer/juicer.js"></script> <script src="~/Content/Scripts/m_pager.js"></script> <script src="~/Content/Scripts/tree/tree.js"></script> @RenderSection("scripts", required: false) </body> </html>
二、編輯器配置類設定
本系統採用富文字編輯器編輯,在使用前,我們需要更改編輯器包中的原生配置以及建立一些基礎類,下面先看看編輯器的幫助類:
1、我們需要在業務層中的BaseUtility檔案下建立Ueditor資料夾,然後在把編輯器的幫助類和設定放在下面:
(1)Config.cs
using Newtonsoft.Json; using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; using System.Dynamic; using System.IO; using System.Linq; using System.Web; namespace IA.Business.Ueditor { /// <summary> /// Config 的摘要說明 /// </summary> public static class Config { private static bool noCache = true; private static JObject BuildItems() { string configPath = @"~/Content/Scripts/ueditor/config.json"; var json = File.ReadAllText(HttpContext.Current.Server.MapPath(configPath)); return JObject.Parse(json); } public static JObject Items { get { if (noCache || _Items == null) { _Items = BuildItems(); } return _Items; } } private static JObject _Items; public static T GetValue<T>(string key) { return Items[key].Value<T>(); } public static String[] GetStringList(string key) { return Items[key].Select(x => x.Value<String>()).ToArray(); } public static String GetString(string key) { return GetValue<String>(key); } public static int GetInt(string key) { return GetValue<int>(key); } } }
(2)ConfigHandler.cs
using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace IA.Business.Ueditor { /// <summary> /// Config 的摘要說明 /// </summary> public class ConfigHandler : Handler { public ConfigHandler(HttpContext context) : base(context) { } public override void Process() { WriteJson(Config.Items); } } }
(3)CrawlerHandler.cs
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; using System.Web; namespace IA.Business.Ueditor { /// <summary> /// Crawler 的摘要說明 /// </summary> public class CrawlerHandler : Handler { private string[] Sources; private Crawler[] Crawlers; public CrawlerHandler(HttpContext context) : base(context) { } public override void Process() { Sources = Request.Form.GetValues("source[]"); if (Sources == null || Sources.Length == 0) { WriteJson(new { state = "引數錯誤:沒有指定抓取源" }); return; } Crawlers = Sources.Select(x => new Crawler(x, Server).Fetch()).ToArray(); WriteJson(new { state = "SUCCESS", list = Crawlers.Select(x => new { state = x.State, source = x.SourceUrl, url = x.ServerUrl }) }); } } public class Crawler { public string SourceUrl { get; set; } public string ServerUrl { get; set; } public string State { get; set; } private HttpServerUtility Server { get; set; } public Crawler(string sourceUrl, HttpServerUtility server) { this.SourceUrl = sourceUrl; this.Server = server; } public Crawler Fetch() { var request = HttpWebRequest.Create(this.SourceUrl) as HttpWebRequest; using (var response = request.GetResponse() as HttpWebResponse) { if (response.StatusCode != HttpStatusCode.OK) { State = "Url returns " + response.StatusCode + ", " + response.StatusDescription; return this; } if (response.ContentType.IndexOf("image") == -1) { State = "Url is not an image"; return this; } ServerUrl = PathFormatter.Format(Path.GetFileName(this.SourceUrl), Config.GetString("catcherPathFormat")); var savePath = Server.MapPath(ServerUrl); if (!Directory.Exists(Path.GetDirectoryName(savePath))) { Directory.CreateDirectory(Path.GetDirectoryName(savePath)); } try { var stream = response.GetResponseStream(); var reader = new BinaryReader(stream); byte[] bytes; using (var ms = new MemoryStream()) { byte[] buffer = new byte[4096]; int count; while ((count = reader.Read(buffer, 0, buffer.Length)) != 0) { ms.Write(buffer, 0, count); } bytes = ms.ToArray(); } File.WriteAllBytes(savePath, bytes); State = "SUCCESS"; } catch (Exception e) { State = "抓取錯誤:" + e.Message; } return this; } } } }
(4)Handler.cs
using System; using System.Collections.Generic; using System.Linq; using System.Web; using Newtonsoft.Json; namespace IA.Business.Ueditor { /// <summary> /// Handler 的摘要說明 /// </summary> public abstract class Handler { public Handler(HttpContext context) { this.Request = context.Request; this.Response = context.Response; this.Context = context; this.Server = context.Server; } public abstract void Process(); protected void WriteJson(object response) { string jsonpCallback = Request["callback"], json = JsonConvert.SerializeObject(response); if (String.IsNullOrWhiteSpace(jsonpCallback)) { Response.AddHeader("Content-Type", "text/plain"); Response.Write(json); } else { Response.AddHeader("Content-Type", "application/javascript"); Response.Write(String.Format("{0}({1});", jsonpCallback, json)); } Response.End(); } public HttpRequest Request { get; private set; } public HttpResponse Response { get; private set; } public HttpContext Context { get; private set; } public HttpServerUtility Server { get; private set; } } }
(5)ListFileHandler.cs
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Web; namespace IA.Business.Ueditor { /// <summary> /// FileManager 的摘要說明 /// </summary> public class ListFileManager : Handler { enum ResultState { Success, InvalidParam, AuthorizError, IOError, PathNotFound } private int Start; private int Size; private int Total; private ResultState State; private String PathToList; private String[] FileList; private String[] SearchExtensions; public ListFileManager(HttpContext context, string pathToList, string[] searchExtensions) : base(context) { this.SearchExtensions = searchExtensions.Select(x => x.ToLower()).ToArray(); this.PathToList = pathToList; } public override void Process() { try { Start = String.IsNullOrEmpty(Request["start"]) ? 0 : Convert.ToInt32(Request["start"]); Size = String.IsNullOrEmpty(Request["size"]) ? Config.GetInt("imageManagerListSize") : Convert.ToInt32(Request["size"]); } catch (FormatException) { State = ResultState.InvalidParam; WriteResult(); return; } var buildingList = new List<String>(); try { var localPath = Server.MapPath(PathToList); buildingList.AddRange(Directory.GetFiles(localPath, "*", SearchOption.AllDirectories) .Where(x => SearchExtensions.Contains(Path.GetExtension(x).ToLower())) .Select(x => PathToList + x.Substring(localPath.Length).Replace("\\", "/"))); Total = buildingList.Count; FileList = buildingList.OrderBy(x => x).Skip(Start).Take(Size).ToArray(); } catch (UnauthorizedAccessException) { State = ResultState.AuthorizError; } catch (DirectoryNotFoundException) { State = ResultState.PathNotFound; } catch (IOException) { State = ResultState.IOError; } finally { WriteResult(); } } private void WriteResult() { WriteJson(new { state = GetStateString(), list = FileList == null ? null : FileList.Select(x => new { url = x }), start = Start, size = Size, total = Total }); } private string GetStateString() { switch (State) { case ResultState.Success: return "SUCCESS"; case ResultState.InvalidParam: return "引數不正確"; case ResultState.PathNotFound: return "路徑不存在"; case ResultState.AuthorizError: return "檔案系統許可權不足"; case ResultState.IOError: return "檔案系統讀取錯誤"; } return "未知錯誤"; } } }
(6)NotSupportedHandler.cs
using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace IA.Business.Ueditor { /// <summary> /// NotSupportedHandler 的摘要說明 /// </summary> public class NotSupportedHandler : Handler { public NotSupportedHandler(HttpContext context) : base(context) { } public override void Process() { WriteJson(new { state = "action 引數為空或者 action 不被支援。" }); } } }
(7)PathFormater.cs
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text.RegularExpressions; using System.Web; namespace IA.Business.Ueditor { /// <summary> /// PathFormater 的摘要說明 /// </summary> public static class PathFormatter { public static string Format(string originFileName, string pathFormat) { if (String.IsNullOrWhiteSpace(pathFormat)) { pathFormat = "{filename}{rand:6}"; } var invalidPattern = new Regex(@"[\\\/\:\*\?\042\<\>\|]"); originFileName = invalidPattern.Replace(originFileName, ""); string extension = Path.GetExtension(originFileName); string filename = Path.GetFileNameWithoutExtension(originFileName); pathFormat = pathFormat.Replace("{filename}", filename); pathFormat = new Regex(@"\{rand(\:?)(\d+)\}", RegexOptions.Compiled).Replace(pathFormat, new MatchEvaluator(delegate(Match match) { var digit = 6; if (match.Groups.Count > 2) { digit = Convert.ToInt32(match.Groups[2].Value); } var rand = new Random(); return rand.Next((int)Math.Pow(10, digit), (int)Math.Pow(10, digit + 1)).ToString(); })); pathFormat = pathFormat.Replace("{time}", DateTime.Now.Ticks.ToString()); pathFormat = pathFormat.Replace("{yyyy}", DateTime.Now.Year.ToString()); pathFormat = pathFormat.Replace("{yy}", (DateTime.Now.Year % 100).ToString("D2")); pathFormat = pathFormat.Replace("{mm}", DateTime.Now.Month.ToString("D2")); pathFormat = pathFormat.Replace("{dd}", DateTime.Now.Day.ToString("D2")); pathFormat = pathFormat.Replace("{hh}", DateTime.Now.Hour.ToString("D2")); pathFormat = pathFormat.Replace("{ii}", DateTime.Now.Minute.ToString("D2")); pathFormat = pathFormat.Replace("{ss}", DateTime.Now.Second.ToString("D2")); return pathFormat + extension; } } }
(8)UploadHandler.cs
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text.RegularExpressions; using System.Web; using Bobo.Utilities; namespace IA.Business.Ueditor { /// <summary> /// UploadHandler 的摘要說明 /// </summary> public class UploadHandler : Handler { public UploadConfig UploadConfig { get; private set; } public UploadResult Result { get; private set; } public UploadHandler(HttpContext context, UploadConfig config) : base(context) { this.UploadConfig = config; this.Result = new UploadResult() { State = UploadState.Unknown }; } public override void Process() { byte[] uploadFileBytes = null; string uploadFileName = null; if (UploadConfig.Base64) { uploadFileName = UploadConfig.Base64Filename; uploadFileBytes = Convert.FromBase64String(Request[UploadConfig.UploadFieldName]); } else { var file = Request.Files[UploadConfig.UploadFieldName]; uploadFileName = file.FileName; if (!CheckFileType(uploadFileName)) { Result.State = UploadState.TypeNotAllow; WriteResult(); return; } if (!CheckFileSize(file.ContentLength)) { Result.State = UploadState.SizeLimitExceed; WriteResult(); return; } uploadFileBytes = new byte[file.ContentLength]; try { file.InputStream.Read(uploadFileBytes, 0, file.ContentLength); } catch (Exception) { Result.State = UploadState.NetworkError; WriteResult(); } } Result.OriginFileName = uploadFileName; var savePath = PathFormatter.Format(uploadFileName, UploadConfig.PathFormat); //百度編輯器附件外移,檢測路徑(NC) var localPath = Server.MapPath(savePath); //ConfigHelper.GetSystemConfig("SystemConfig", "fileUploadPath", "UeditorPath") + Result.OriginFileName; try { if (!Directory.Exists(Path.GetDirectoryName(localPath))) { Directory.CreateDirectory(Path.GetDirectoryName(localPath)); } File.WriteAllBytes(localPath, uploadFileBytes); //百度編輯器附件讀取,檢測路徑(NC) Result.Url = savePath; //ConfigHelper.GetSystemConfig("SystemConfig", "fileUploadPath", "UeditorVirtualPath") + Result.OriginFileName; Result.State = UploadState.Success; } catch (Exception e) { Result.State = UploadState.FileAccessError; Result.ErrorMessage = e.Message; } finally { WriteResult(); } } private void WriteResult() { this.WriteJson(new { state = GetStateMessage(Result.State), url = Result.Url, title = Result.OriginFileName, original = Result.OriginFileName, error = Result.ErrorMessage }); } private string GetStateMessage(UploadState state) { switch (state) { case UploadState.Success: return "SUCCESS"; case UploadState.FileAccessError: return "檔案訪問出錯,請檢查寫入許可權"; case UploadState.SizeLimitExceed: return "檔案大小超出伺服器限制"; case UploadState.TypeNotAllow: return "不允許的檔案格式"; case UploadState.NetworkError: return "網路錯誤"; } return "未知錯誤"; } private bool CheckFileType(string filename) { var fileExtension = Path.GetExtension(filename).ToLower(); return UploadConfig.AllowExtensions.Select(x => x.ToLower()).Contains(fileExtension); } private bool CheckFileSize(int size) { return size < UploadConfig.SizeLimit; } } public class UploadConfig { /// <summary> /// 檔案命名規則 /// </summary> public string PathFormat { get; set; } /// <summary> /// 上傳表單域名稱 /// </summary> public string UploadFieldName { get; set; } /// <summary> /// 上傳大小限制 /// </summary> public int SizeLimit { get; set; } /// <summary> /// 上傳允許的檔案格式 /// </summary> public string[] AllowExtensions { get; set; } /// <summary> /// 檔案是否以 Base64 的形式上傳 /// </summary> public bool Base64 { get; set; } /// <summary> /// Base64 字串所表示的檔名 /// </summary> public string Base64Filename { get; set; } } public class UploadResult { public UploadState State { get; set; } public string Url { get; set; } public string OriginFileName { get; set; } public string ErrorMessage { get; set; } } public enum UploadState { Success = 0, SizeLimitExceed = -1, TypeNotAllow = -2, FileAccessError = -3, NetworkError = -4, Unknown = 1, } }
(1)config.json檔案主要是設定編輯器中上傳的檔案大小、格式、路徑、以及方法(檔案中的註釋,若你使用的是Newtonsoft.Json.dll, v4.5.0.0以下的版本,json檔案不能加註釋,否則報錯):
/* 前後端通訊相關的配置,註釋只允許使用多行方式 */ { /* 上傳圖片配置項 */ "imageActionName": "uploadimage", /* 執行上傳圖片的action名稱 */ "imageFieldName": "upfile", /* 提交的圖片表單名稱 */ "imageMaxSize": 51200000, /* 上傳大小限制,單位B */ "imageAllowFiles": [".png", ".jpg", ".jpeg", ".gif", ".bmp"], /* 上傳圖片格式顯示 */ "imageCompressEnable": true, /* 是否壓縮圖片,預設是true */ "imageCompressBorder": 900, /* 圖片壓縮最長邊限制 */ "imageInsertAlign": "none", /* 插入的圖片浮動方式 */ "imageUrlPrefix": "", /* 圖片訪問路徑字首 */ "imagePathFormat": "/Resource/Article/UEupload/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上傳儲存路徑,可以自定義儲存路徑和檔名格式 */ /* {filename} 會替換成原檔名,配置這項需要注意中文亂碼問題 */ /* {rand:6} 會替換成隨機數,後面的數字是隨機數的位數 */ /* {time} 會替換成時間戳 */ /* {yyyy} 會替換成四位年份 */ /* {yy} 會替換成兩位年份 */ /* {mm} 會替換成兩位月份 */ /* {dd} 會替換成兩位日期 */ /* {hh} 會替換成兩位小時 */ /* {ii} 會替換成兩位分鐘 */ /* {ss} 會替換成兩位秒 */ /* 非法字元 \ : * ? " < > | */ /* 具請體看線上文件: fex.baidu.com/ueditor/#use-format_upload_filename */ /* 塗鴉圖片上傳配置項 */ "scrawlActionName": "uploadscrawl", /* 執行上傳塗鴉的action名稱 */ "scrawlFieldName": "upfile", /* 提交的圖片表單名稱 */ "scrawlPathFormat": "/Resource/Article/UEupload/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上傳儲存路徑,可以自定義儲存路徑和檔名格式 */ "scrawlMaxSize": 51200000, /* 上傳大小限制,單位B */ "scrawlUrlPrefix": "", /* 圖片訪問路徑字首 */ "scrawlInsertAlign": "none", /* 截圖工具上傳 */ "snapscreenActionName": "uploadimage", /* 執行上傳截圖的action名稱 */ "snapscreenPathFormat": "/Resource/Article/UEupload/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上傳儲存路徑,可以自定義儲存路徑和檔名格式 */ "snapscreenUrlPrefix": "", /* 圖片訪問路徑字首 */ "snapscreenInsertAlign": "none", /* 插入的圖片浮動方式 */ /* 抓取遠端圖片配置 */ "catcherLocalDomain": ["127.0.0.1", "localhost", "img.baidu.com"], "catcherActionName": "catchimage", /* 執行抓取遠端圖片的action名稱 */ "catcherFieldName": "source", /* 提交的圖片列表表單名稱 */ "catcherPathFormat": "/Resource/Article/UEupload/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上傳儲存路徑,可以自定義儲存路徑和檔名格式 */ "catcherUrlPrefix": "", /* 圖片訪問路徑字首 */ "catcherMaxSize": 51200000, /* 上傳大小限制,單位B */ "catcherAllowFiles": [".png", ".jpg", ".jpeg", ".gif", ".bmp"], /* 抓取圖片格式顯示 */ /* 上傳視訊配置 */ "videoActionName": "uploadvideo", /* 執行上傳視訊的action名稱 */ "videoFieldName": "upfile", /* 提交的視訊表單名稱 */ "videoPathFormat": "/Resource/Article/UEupload/video/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上傳儲存路徑,可以自定義儲存路徑和檔名格式 */ "videoUrlPrefix": "", /* 視訊訪問路徑字首 */ "videoMaxSize": 102400000, /* 上傳大小限制,單位B,預設100MB */ "videoAllowFiles": [ ".flv", ".swf", ".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg", ".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav", ".mid"], /* 上傳視訊格式顯示 */ /* 上傳檔案配置 */ "fileActionName": "uploadfile", /* controller裡,執行上傳視訊的action名稱 */ "fileFieldName": "upfile", /* 提交的檔案表單名稱 */ "filePathFormat": "/Resource/Article/UEupload/file/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上傳儲存路徑,可以自定義儲存路徑和檔名格式 */ "fileUrlPrefix": "", /* 檔案訪問路徑字首 */ "fileMaxSize": 51200000, /* 上傳大小限制,單位B,預設50MB */ "fileAllowFiles": [ ".png", ".jpg", ".jpeg", ".gif", ".bmp", ".flv", ".swf", ".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg", ".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav", ".mid", ".rar", ".zip", ".tar", ".gz", ".7z", ".bz2", ".cab", ".iso", ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".pdf", ".txt", ".md", ".xml" ], /* 上傳檔案格式顯示 */ /* 列出指定目錄下的圖片 */ "imageManagerActionName": "listimage", /* 執行圖片管理的action名稱 */ "imageManagerListPath": "/Resource/Article/UEupload/image", /* 指定要列出圖片的目錄 */ "imageManagerListSize": 20, /* 每次列出檔案數量 */ "imageManagerUrlPrefix": "", /* 圖片訪問路徑字首 */ "imageManagerInsertAlign": "none", /* 插入的圖片浮動方式 */ "imageManagerAllowFiles": [".png", ".jpg", ".jpeg", ".gif", ".bmp"], /* 列出的檔案型別 */ /* 列出指定目錄下的檔案 */ "fileManagerActionName": "listfile", /* 執行檔案管理的action名稱 */ "fileManagerListPath": "/Resource/Article/UEupload/file", /* 指定要列出檔案的目錄 */ "fileManagerUrlPrefix": "", /* 檔案訪問路徑字首 */ "fileManagerListSize": 20, /* 每次列出檔案數量 */ "fileManagerAllowFiles": [ ".png", ".jpg", ".jpeg", ".gif", ".bmp", ".flv", ".swf", ".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg", ".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav", ".mid", ".rar", ".zip", ".tar", ".gz", ".7z", ".bz2", ".cab", ".iso", ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".pdf", ".txt", ".md", ".xml" ] /* 列出的檔案型別 */ }
(2)controller.ashx 檔案上傳處理類
<%@ WebHandler Language="C#" Class="UEditorHandler" %> using System; using System.Web; using System.IO; using System.Collections; using Newtonsoft.Json; using IA.Business.Ueditor; public class UEditorHandler : IHttpHandler { public void ProcessRequest(HttpContext context) { Handler action = null; switch (context.Request["action"]) { case "config": action = new ConfigHandler(context); break; case "uploadimage": action = new UploadHandler(context, new UploadConfig() { AllowExtensions = Config.GetStringList("imageAllowFiles"), PathFormat = Config.GetString("imagePathFormat"), SizeLimit = Config.GetInt("imageMaxSize"), UploadFieldName = Config.GetString("imageFieldName") }); break; case "uploadscrawl": action = new UploadHandler(context, new UploadConfig() { AllowExtensions = new string[] { ".png" }, PathFormat = Config.GetString("scrawlPathFormat"), SizeLimit = Config.GetInt("scrawlMaxSize"), UploadFieldName = Config.GetString("scrawlFieldName"), Base64 = true, Base64Filename = "scrawl.png" }); break; case "uploadvideo": action = new UploadHandler(context, new UploadConfig() { AllowExtensions = Config.GetStringList("videoAllowFiles"), PathFormat = Config.GetString("videoPathFormat"), SizeLimit = Config.GetInt("videoMaxSize"), UploadFieldName = Config.GetString("videoFieldName") }); break; case "uploadfile": action = new UploadHandler(context, new UploadConfig() { AllowExtensions = Config.GetStringList("fileAllowFiles"), PathFormat = Config.GetString("filePathFormat"), SizeLimit = Config.GetInt("fileMaxSize"), UploadFieldName = Config.GetString("fileFieldName") }); break; case "listimage": action = new ListFileManager(context, Config.GetString("imageManagerListPath"), Config.GetStringList("imageManagerAllowFiles")); break; case "listfile": action = new ListFileManager(context, Config.GetString("fileManagerListPath"), Config.GetStringList("fileManagerAllowFiles")); break; case "catchimage": action = new CrawlerHandler(context); break; default: action = new NotSupportedHandler(context); break; } action.Process(); } public bool IsReusable { get { return false; } } }