NopCommerce 3.80框架研究(三)替换tinymce 为KindEditor

NopCommerce 自带的编辑器tinymce 功能不是很全。所以尝试将其替换为功能更强大的 KindEditor 并替实现文件上传和在线浏览功能

首先下载 并解压到如下位置

请注意这里是部署在Nop.Web站点下,前后台分离部署的情况请另作调整

部署时记得删除Kindedtor/asp.net/文件夹

修改富文本编辑器模板:Presentation/Nop.Web/Administration/Views/Shared/EditorTemplates/RichEditor.cshtml

@model String

@using Nop.Web.Framework.UI;

@{
    Html.AddCssFileParts("~/Content/kindeditor/themes/default/default.css");
    Html.AddScriptParts("~/Content/kindeditor/kindeditor-all-min.js");
}

<script>
    KindEditor.ready(function (K) {
        window.editor = K.create(‘#@ViewData.TemplateInfo.GetFullHtmlFieldId(string.Empty)‘, {
            width: 1050,
            height: 650,
            uploadJson: ‘@Url.Action("ProcessRequest", "KindEditor", new{ a= "UPLOAD" })‘,
            fileManagerJson: ‘@Url.Action("ProcessRequest", "KindEditor", new { a = "MANAGE" })‘,
            allowFileManager: true
        });
    });
</script>

@Html.TextArea(string.Empty, /* Name suffix */
    ViewData.TemplateInfo.FormattedModelValue /* Initial value */
)

添加文件上传控制器 KindEditorController.cs

using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.IO.Compression;
using System.Text.RegularExpressions;
using System.Web;
using Nop.Core;
using Nop.Services.Security;
using Nop.Web.Framework.Security;
using System.Globalization;
//[email protected] Han //http://qbit.cnblogs.com///2016-12-3 23:33:19//http://www.cnblogs.com/Qbit/p/NopCommerce_KindEditor.html

namespace Nop.Admin.Controllers
{
    //Controller for Roxy fileman (http://www.roxyfileman.com/) for TinyMCE editor
    //the original file was \RoxyFileman-1.4.3-net\fileman\asp_net\main.ashx
    //some custom changes by wooncherk contribution

    //do not validate request token (XSRF)
    [AdminAntiForgery(true)]
    public class KindEditorController : BaseAdminController
    {
        #region Fields

        //custom code by nopCommerce team
        private readonly IPermissionService _permissionService;
        private readonly HttpContextBase context;
        private readonly HttpResponseBase response;

        #endregion

        #region Ctor

        //custom code by nopCommerce team
        public KindEditorController(IPermissionService permissionService, HttpContextBase context)
        {
            this._permissionService = permissionService;
            this.context = context;
            this.response = this.context.Response;
        }

        #endregion

        #region Methods

        public void ProcessRequest()
        {
            string action = "UPLOAD";

            //custom code by nopCommerce team
            if (!_permissionService.Authorize(StandardPermissionProvider.HtmlEditorManagePictures))
                showError("You don‘t have required permission");

            try
            {
                if (context.Request["a"] != null)
                    action = (string)context.Request["a"];

                switch (action.ToUpper())
                {
                    case "UPLOAD":
                        Upload(context);
                        break;
                    case "MANAGE":
                        Manage(context);
                        break;
                    default:
                        break;
                }

            }
            catch (Exception ex)
            {
                showError(ex.ToString());
            }

        }
        private void Manage(HttpContextBase context)
        {
            String aspxUrl = context.Request.Path.Substring(0, context.Request.Path.LastIndexOf("/") + 1);

            //根目录路径,相对路径
            String rootPath = "/Content/attached/";
            //根目录URL,可以指定绝对路径,比如 http://www.yoursite.com/attached/
            String rootUrl =  "/Content/attached/";
            //图片扩展名
            String fileTypes = "gif,jpg,jpeg,png,bmp";

            String currentPath = "";
            String currentUrl = "";
            String currentDirPath = "";
            String moveupDirPath = "";

            String dirPath = context.Server.MapPath(rootPath);
            String dirName = context.Request.QueryString["dir"];
            if (!String.IsNullOrEmpty(dirName))
            {
                if (Array.IndexOf("image,flash,media,file".Split(‘,‘), dirName) == -1)
                {
                    context.Response.Write("Invalid Directory name.");
                    context.Response.End();
                }
                dirPath += dirName + "/";
                rootUrl += dirName + "/";
                if (!Directory.Exists(dirPath))
                {
                    Directory.CreateDirectory(dirPath);
                }
            }

            //根据path参数,设置各路径和URL
            String path = context.Request.QueryString["path"];
            path = String.IsNullOrEmpty(path) ? "" : path;
            if (path == "")
            {
                currentPath = dirPath;
                currentUrl = rootUrl;
                currentDirPath = "";
                moveupDirPath = "";
            }
            else
            {
                currentPath = dirPath + path;
                currentUrl = rootUrl + path;
                currentDirPath = path;
                moveupDirPath = Regex.Replace(currentDirPath, @"(.*?)[^\/]+\/$", "$1");
            }

            //排序形式,name or size or type
            String order = context.Request.QueryString["order"];
            order = String.IsNullOrEmpty(order) ? "" : order.ToLower();

            //不允许使用..移动到上一级目录
            if (Regex.IsMatch(path, @"\.\."))
            {
                context.Response.Write("Access is not allowed.");
                context.Response.End();
            }
            //最后一个字符不是/
            if (path != "" && !path.EndsWith("/"))
            {
                context.Response.Write("Parameter is not valid.");
                context.Response.End();
            }
            //目录不存在或不是目录
            if (!Directory.Exists(currentPath))
            {
                context.Response.Write("Directory does not exist.");
                context.Response.End();
            }

            //遍历目录取得文件信息
            string[] dirList = Directory.GetDirectories(currentPath);
            string[] fileList = Directory.GetFiles(currentPath);

            switch (order)
            {
                case "size":
                    Array.Sort(dirList, new NameSorter());
                    Array.Sort(fileList, new SizeSorter());
                    break;
                case "type":
                    Array.Sort(dirList, new NameSorter());
                    Array.Sort(fileList, new TypeSorter());
                    break;
                case "name":
                default:
                    Array.Sort(dirList, new NameSorter());
                    Array.Sort(fileList, new NameSorter());
                    break;
            }

            Hashtable result = new Hashtable();
            result["moveup_dir_path"] = moveupDirPath;
            result["current_dir_path"] = currentDirPath;
            result["current_url"] = currentUrl;
            result["total_count"] = dirList.Length + fileList.Length;
            List<Hashtable> dirFileList = new List<Hashtable>();
            result["file_list"] = dirFileList;
            for (int i = 0; i < dirList.Length; i++)
            {
                DirectoryInfo dir = new DirectoryInfo(dirList[i]);
                Hashtable hash = new Hashtable();
                hash["is_dir"] = true;
                hash["has_file"] = (dir.GetFileSystemInfos().Length > 0);
                hash["filesize"] = 0;
                hash["is_photo"] = false;
                hash["filetype"] = "";
                hash["filename"] = dir.Name;
                hash["datetime"] = dir.LastWriteTime.ToString("yyyy-MM-dd HH:mm:ss");
                dirFileList.Add(hash);
            }
            for (int i = 0; i < fileList.Length; i++)
            {
                FileInfo file = new FileInfo(fileList[i]);
                Hashtable hash = new Hashtable();
                hash["is_dir"] = false;
                hash["has_file"] = false;
                hash["filesize"] = file.Length;
                hash["is_photo"] = (Array.IndexOf(fileTypes.Split(‘,‘), file.Extension.Substring(1).ToLower()) >= 0);
                hash["filetype"] = file.Extension.Substring(1);
                hash["filename"] = file.Name;
                hash["datetime"] = file.LastWriteTime.ToString("yyyy-MM-dd HH:mm:ss");
                dirFileList.Add(hash);
            }
            context.Response.Write(Newtonsoft.Json.JsonConvert.SerializeObject(result));
            context.Response.End();
        }

        public void Upload(HttpContextBase context)
        {
            String aspxUrl = context.Request.Path.Substring(0, context.Request.Path.LastIndexOf("/") + 1);

            //文件保存目录路径
            String savePath = "/Content/attached/";

            //文件保存目录URL
            String saveUrl =  "/Content/attached/";

            //定义允许上传的文件扩展名
            Hashtable extTable = new Hashtable();
            extTable.Add("image", "gif,jpg,jpeg,png,bmp");
            extTable.Add("flash", "swf,flv");
            extTable.Add("media", "swf,flv,mp3,wav,wma,wmv,mid,avi,mpg,asf,rm,rmvb");
            extTable.Add("file", "doc,docx,xls,xlsx,ppt,htm,html,txt,zip,rar,gz,bz2");

            //最大文件大小
            int maxSize = 1000000;

            var imgFile = context.Request.Files["imgFile"];
            if (imgFile == null)
            {
                showError("请选择文件。");
            }

            String dirPath = context.Server.MapPath(savePath);
            if (!Directory.Exists(dirPath))
            {
                showError("上传目录不存在。");
            }

            String dirName = context.Request.QueryString["dir"];
            if (String.IsNullOrEmpty(dirName))
            {
                dirName = "image";
            }
            if (!extTable.ContainsKey(dirName))
            {
                showError("目录名不正确。");
            }

            String fileName = imgFile.FileName;
            String fileExt = Path.GetExtension(fileName).ToLower();

            if (imgFile.InputStream == null || imgFile.InputStream.Length > maxSize)
            {
                showError("上传文件大小超过限制。");
            }

            if (String.IsNullOrEmpty(fileExt) || Array.IndexOf(((String)extTable[dirName]).Split(‘,‘), fileExt.Substring(1).ToLower()) == -1)
            {
                showError("上传文件扩展名是不允许的扩展名。\n只允许" + ((String)extTable[dirName]) + "格式。");
            }

            //创建文件夹
            dirPath += dirName + "/";
            saveUrl += dirName + "/";
            if (!Directory.Exists(dirPath))
            {
                Directory.CreateDirectory(dirPath);
            }
            String ymd = DateTime.Now.ToString("yyyyMMdd", DateTimeFormatInfo.InvariantInfo);
            dirPath += ymd + "/";
            saveUrl += ymd + "/";
            if (!Directory.Exists(dirPath))
            {
                Directory.CreateDirectory(dirPath);
            }

            String newFileName = DateTime.Now.ToString("yyyyMMddHHmmss_ffff", DateTimeFormatInfo.InvariantInfo) + fileExt;
            String filePath = dirPath + newFileName;

            imgFile.SaveAs(filePath);

            String fileUrl = saveUrl + newFileName;

            Hashtable hash = new Hashtable();
            hash["error"] = 0;
            hash["url"] = fileUrl;
            context.Response.Write(Newtonsoft.Json.JsonConvert.SerializeObject(hash));
            context.Response.End();
        }

        #endregion

        #region Utitlies
        private void showError(string message)
        {
            Hashtable hash = new Hashtable();
            hash["error"] = 1;
            hash["message"] = message;
            context.Response.Write(Newtonsoft.Json.JsonConvert.SerializeObject(hash));
            context.Response.End();
        }

        #region KindEditorClass
        public class NameSorter : IComparer
        {
            public int Compare(object x, object y)
            {
                if (x == null && y == null)
                {
                    return 0;
                }
                if (x == null)
                {
                    return -1;
                }
                if (y == null)
                {
                    return 1;
                }
                FileInfo xInfo = new FileInfo(x.ToString());
                FileInfo yInfo = new FileInfo(y.ToString());

                return xInfo.FullName.CompareTo(yInfo.FullName);
            }
        }

        public class SizeSorter : IComparer
        {
            public int Compare(object x, object y)
            {
                if (x == null && y == null)
                {
                    return 0;
                }
                if (x == null)
                {
                    return -1;
                }
                if (y == null)
                {
                    return 1;
                }
                FileInfo xInfo = new FileInfo(x.ToString());
                FileInfo yInfo = new FileInfo(y.ToString());

                return xInfo.Length.CompareTo(yInfo.Length);
            }
        }

        public class TypeSorter : IComparer
        {
            public int Compare(object x, object y)
            {
                if (x == null && y == null)
                {
                    return 0;
                }
                if (x == null)
                {
                    return -1;
                }
                if (y == null)
                {
                    return 1;
                }
                FileInfo xInfo = new FileInfo(x.ToString());
                FileInfo yInfo = new FileInfo(y.ToString());

                return xInfo.Extension.CompareTo(yInfo.Extension);
            }
        }
        #endregion
        #endregion

    }
}

测试效果:

原文地址:http://www.cnblogs.com/Qbit/p/NopCommerce_KindEditor.html

时间: 2024-08-10 17:18:33

NopCommerce 3.80框架研究(三)替换tinymce 为KindEditor的相关文章

NopCommerce 3.80框架研究(二) MVC 表示层与数据验证

表示层框架结构 /Views/Shared/_Root.Head.cshtml /Views/Shared/_Root.cshtml /Views/Shared/_ColumnsOne.cshtml /Views/_ViewStart.cshtml 最外层: /Views/Shared/_Root.Head.cshtml 根框架<html>根节点 其他3个Layout全部包含在此 布局页面的Body 中 /Views/Shared/_Root.cshtml  包含商城网页头部 和导航菜单,其中

Prism框架研究(三)

这一篇主要用来介绍一下基于Prism Library中的核心服务以及如何配置Container,还有一个重要的部分是如何管理各个组件之间的依赖性,下面就这些内容来做一一的介绍. 1 Prism中的核心服务 IModuleManager:为能够检索和初始化应用程序的各个模块的服务定义接口. IModuleCatalog:包含一个应用程序各个模块的元数据,这个Prism Libray几种不同的Catalog. IModuleInitializer:初始化应用程序的各个模块. IRegionManag

【原创】NIO框架入门(三):iOS与MINA2、Netty4的跨平台UDP双向通信实战

前言 本文将演示一个iOS客户端程序,通过UDP协议与两个典型的NIO框架服务端,实现跨平台双向通信的完整Demo.服务端将分别用MINA2和Netty4进行实现,而通信时服务端你只需选其一就行了.同时用MINA2和Netty4分别实现服务端的目的,是因为很多人都在纠结到底是用MINA还是Netty来实现高并发的Java网络通信服务端,在此干脆两个都实现了,就看你怎么选择了,够吊吧. NIO框架的流行,使得开发大并发.高性能的互联网服务端成为可能.这其中最流行的无非就是MINA和Netty了,M

Java面试准备之JVM详细研究三(类加载机制)

类加载过程 一个类从编写完成后,编译为字节码之后,它要装载进内存有七个阶段: 加载 => (验证-> 准备-> 解析)=> 初始化=> 使用=> 卸载 括号中的三个步骤可以整合成为 “连接”步骤.其中的步骤并不是一个阶段结束,一个阶段才开始的.只是说他们的开始阶段基本遵循此顺序(解析阶段更是可能在使用的时候才发生,目的是配合动态绑定),这些阶段都是互相交叉的混合式进行的,通常会在一个阶段执行过程中调用或激活另一个阶段. 1.加载 ”加载“的过程是”类加载“过程的一个阶段

JAVA 虚拟机深入研究(三)——Java内存区域

JAVA 虚拟机深入研究(一)--关于Java的一些历史 JAVA 虚拟机深入研究(二)--JVM虚拟机发展以及一些Java的新东西 JAVA 虚拟机深入研究(三)--Java内存区域 Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的围城,城外的人想进去,城里的人想出来. Java运行的时候会把内存分为若干个,他们各有各的用途,每块区域的创建和销毁都是相对独立的,有的跟虚拟机一起混,有的则抱着用户的大腿同生共死. 按照第七版的<Java虚拟机规范>规定,JVM所管理的内存包括以下

黑马程序员-----集合框架类(三) Map集合

黑马程序员-----集合框架类(三) Map集合 1.1 Map集合:该集合存储键值对.一对一对往里存.而且要保证键的唯一性. 1,添加. put(K key, V value) putAll(Map<? extends K,? extends V> m) 2,删除. clear() remove(Object key) 3,判断. containsValue(Object value) containsKey(Object key) isEmpty() 4,获取. get(Object ke

Python-Django框架研究_登陆查看数据添加数据_20191104

Python-Django框架研究: 研究的目的: 第一步只做一件事,就是使用Django做一个注册登录的功能,其他的统统不管, 学习方法: 绝对不能自己学,一定要借助视频的力量,博客的力量,高速度学习,进行强学习, 首先是安装Django: pip install django==1.11.11 -i https://pypi.tuna.tsinghua.edu.cn/simple cmd中输入Django-admin,出现内容就说明安装成功了, 然后创建第一个Django项目: 使用pych

游戏UI框架设计(三) : 窗体的层级管理

游戏UI框架设计(三) ---窗体的层级管理 UI框架中UI窗体的"层级管理",最核心的问题是如何进行窗体的显示管理.窗体(预设)的显示我们前面定义了三种类型: 普通.隐藏其他.反向切换.代码如下: "普通显示"模式允许多个窗体同时显示,这种类型应用最多.例如RPG中的主城界面(见下图). "隐藏其他界面" 模式一般应用于全局性的窗体.我们在开发此类窗体时,为了减少UI渲染压力.提高Unity渲染效率,则设置被覆盖的窗体为"不可见&qu

Struts2框架学习(三) 数据处理

Struts2框架学习(三) 数据处理 Struts2框架框架使用OGNL语言和值栈技术实现数据的流转处理. 值栈就相当于一个容器,用来存放数据,而OGNL是一种快速查询数据的语言. 值栈:ValueStack一种数据结构,操作数据的方式为:先进后出 OGNL : Object-GraphNavigation Language(对象图形导航语言)将多个对象的关系使用一种树形的结构展现出来,更像一个图形,那么如果需要对树形结构的节点数据进行操作,那么可以使用 对象.属性 的方式进行操作,OGNL技