1. 程式人生 > >ASP.NET MVC 實現頁落網資源分享網站+充值管理+後臺管理(7)之擴充套件基類和區域建立以及文字編輯配置

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的路由對映:

17.png

注意區域裡面對映設定和名稱的對應。

然後我們在表現層(非區域)的Shared檔案中建立MVC佈局頁_LayoutMange.cshtml和_LayoutForm.cshtml,用來供後臺管理頁面和form表單頁面引用:

18.png

建立好之後,在佈局檔案中引用功能頁面需要用到(頻率高和共用)的樣式檔案、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;
        }
    }
}