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; } } }