Kindeditor 是一套开源的在线HTML编辑器,主要用于让用户在网站上获得所见即所得编辑效果,我们可以用 KindEditor 把传统的多行文本输入框(textarea)替换为可视化的富文本输入框。
快速:体积小,加载速度快
开源:开放源代码,高水平,高品质
底层:内置自定义 DOM 类库,精确操作 DOM
扩展:基于插件的设计,所有功能都是插件,可根据需求增减功能
风格:修改编辑器风格非常容易,只需修改一个 CSS 文件
兼容:支持大部分主流浏览器,比如 IE、Firefox、Safari、Chrome、Opera。
<%@page contentType="text/html;charset=UTF-8" trimDirectiveWhitespaces="true"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <script src="js/jquery.js"></script> <script type="text/javascript"> //kindeditor控件有需要 var basePath = '${pageContext.request.scheme}://${pageContext.request.serverName}:${pageContext.request.serverPort}${pageContext.request.contextPath}/'; </script> <title>测试页面</title> <!-- 编辑器控件 --> <link rel="stylesheet" href="plugins/kindeditor/themes/default/default.css" /> <script charset="utf-8" src="plugins/kindeditor/kindeditor-min.js"></script> <script charset="utf-8" src="plugins/kindeditor/lang/zh_CN.js"></script> <script> var editor; KindEditor.ready(function(K) { editor = K.create('textarea[name="content"]', { allowFileManager : true }); editor.html("你可以测试一下插入文件和插入图片功能,提交后可以在下方看见预览!"); }); function submitForm() { $.ajax({ type: "POST", url: "ajaxForm.do",//ajsx提交表单 data: {"content":editor.html()}, success: function(data) { if(data) { $("textarea[name=content]").val(""); editor.html(""); } }, error: function() { alert("操作失败"); } }); } </script> </head> <body style="background-color: #FFF"> <div class="main"> <div class="wraper"> <form id="form" name="form" class="registerform" action="" onsubmit="return false;" method="post"> <table width="100%" style="table-layout:fixed;padding-left: 10px;" border="0"> <tr> <td style="width:520px;"> <textarea rows="3" cols="10" name="content" style="width:520px;height:400px;visibility:hidden;"></textarea> </td> </tr> <tr> <td style="padding:10px 0 18px 0;"> <input type="button" value="提 交" id="submit" onclick="submitForm();"/> </td> </tr> </table> </form> </div> </div> </body> </html>
使用默认的kindeditor模式中,图片上传路径/kindeditor/plugins/filemanager/filemanager.js中第16行左右的uploadJson和图片管理路径/kindeditor/plugins/filemanager/filemanager.js中第十二行fileManagerJson修改为:basePath+“/kindeditor/file_upload.do” 和basePath+“/kindeditor/file_manager_json.do”
/** * kindeditor文件上传控制器 * @author Rrenchuan.Qin * @date 2013-7-17 下午1:38:19 */ @Controller @RequestMapping("kindeditor") public class KindEditorController { /** * 文件上传 * @param request * @param response * @return * @throws ServletException * @throws IOException * @throws FileUploadException */ @SuppressWarnings("rawtypes") @RequestMapping(value = "file_upload.do") //@ResponseBody public void fileUpload(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException, FileUploadException { ServletContext application = request.getSession().getServletContext(); String savePath = application.getRealPath("/") + "attached/"; // 文件保存目录URL String saveUrl = request.getContextPath() + "/attached/"; // 定义允许上传的文件扩展名 HashMap<String, String> extMap = new HashMap<String, String>(); extMap.put("image", "gif,jpg,jpeg,png,bmp"); extMap.put("flash", "swf,flv"); extMap.put("media", "swf,flv,mp3,wav,wma,wmv,mid,avi,mpg,asf,rm,rmvb"); extMap.put("file", "doc,docx,xls,xlsx,ppt,htm,html,xml,sql,txt,zip,rar,gz,bz2,pdf"); // 最大文件大小 long maxSize = 10000000; response.setContentType("text/html; charset=UTF-8"); if (!ServletFileUpload.isMultipartContent(request)) { writeMsg(response, "请选择文件。"); return; } // 检查目录 File uploadDir = new File(savePath); if (!uploadDir.isDirectory()) { writeMsg(response, "上传目录不存在。"); return; } // 检查目录写权限 if (!uploadDir.canWrite()) { writeMsg(response, "上传目录没有写权限。"); return; } String dirName = request.getParameter("dir"); if (dirName == null) { dirName = "image"; } if (!extMap.containsKey(dirName)) { writeMsg(response, "目录名不正确。"); return; } // 创建文件夹 savePath += dirName + "/"; saveUrl += dirName + "/"; File saveDirFile = new File(savePath); if (!saveDirFile.exists()) { saveDirFile.mkdirs(); } SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd"); String ymd = sdf.format(new Date()); savePath += ymd + "/"; saveUrl += ymd + "/"; File dirFile = new File(savePath); if (!dirFile.exists()) { dirFile.mkdirs(); } FileItemFactory factory = new DiskFileItemFactory(); ServletFileUpload upload = new ServletFileUpload(factory); upload.setHeaderEncoding("UTF-8"); List items = upload.parseRequest(request); Iterator itr = items.iterator(); while (itr.hasNext()) { FileItem item = (FileItem) itr.next(); String fileName = item.getName(); if (!item.isFormField()) { // 检查文件大小 if (item.getSize() > maxSize) { writeMsg(response, "上传文件大小超过限制。"); return; } // 检查扩展名 String fileExt = fileName.substring( fileName.lastIndexOf(".") + 1).toLowerCase(); if (!Arrays.<String> asList(extMap.get(dirName).split(",")) .contains(fileExt)) { writeMsg(response, "上传文件扩展名是不允许的扩展名。\n只允许" + extMap.get(dirName) + "格式。"); return; } SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss"); String newFileName = df.format(new Date()) + "_" + new Random().nextInt(1000) + "." + fileExt; try { File uploadedFile = new File(savePath, newFileName); item.write(uploadedFile); } catch (Exception e) { writeMsg(response, "上传文件失败。"); return; } Map<String, Object> msg = new HashMap<String, Object>(); msg.put("error", 0); msg.put("url", saveUrl + newFileName); //WebUtil.writerJson(response, msg); writeJson(response, msg); } } } /** * 输出信息 * @param response * @param message */ private void writeMsg(HttpServletResponse response, String message) { Map<String, Object> msg = new HashMap<String, Object>(); msg.put("error", 1); msg.put("message", message); //WebUtil.writerJson(response, msg); writeJson(response, msg); } /** *输出json 解决ie * @param response * @param msg */ private void writeJson(HttpServletResponse response, Object msg) { response.reset(); response.setCharacterEncoding("UTF-8"); response.setContentType("text/html"); PrintWriter writer = null; try { writer = response.getWriter(); writer.println(JSON.toJSONString(msg)); writer.flush(); } catch (IOException e) { e.printStackTrace(); } finally { if (writer != null) { try { writer.close(); } catch (Exception e) { e.printStackTrace(); } } } } /** * 文件管理 * @param request * @param response * @throws ServletException * @throws IOException */ @SuppressWarnings({ "rawtypes", "unchecked" }) @RequestMapping(value = "file_manager_json.do") public void fileManager(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { ServletContext application = request.getSession().getServletContext(); ServletOutputStream out = response.getOutputStream(); // 根目录路径,可以指定绝对路径,比如 /var/www/attached/ String rootPath = application.getRealPath("/") + "attached/"; // 根目录URL,可以指定绝对路径,比如 http://www.yoursite.com/attached/ String rootUrl = request.getContextPath() + "/attached/"; // 图片扩展名 String[] fileTypes = new String[] { "gif", "jpg", "jpeg", "png", "bmp" }; String dirName = request.getParameter("dir"); if (dirName != null) { if (!Arrays.<String> asList( new String[] { "image", "flash", "media", "file" }) .contains(dirName)) { out.println("Invalid Directory name."); return; } rootPath += dirName + "/"; rootUrl += dirName + "/"; File saveDirFile = new File(rootPath); if (!saveDirFile.exists()) { saveDirFile.mkdirs(); } } // 根据path参数,设置各路径和URL String path = request.getParameter("path") != null ? request .getParameter("path") : ""; String currentPath = rootPath + path; String currentUrl = rootUrl + path; String currentDirPath = path; String moveupDirPath = ""; if (!"".equals(path)) { String str = currentDirPath.substring(0, currentDirPath.length() - 1); moveupDirPath = str.lastIndexOf("/") >= 0 ? str.substring(0, str.lastIndexOf("/") + 1) : ""; } // 排序形式,name or size or type String order = request.getParameter("order") != null ? request .getParameter("order").toLowerCase() : "name"; // 不允许使用..移动到上一级目录 if (path.indexOf("..") >= 0) { out.println("Access is not allowed."); return; } // 最后一个字符不是/ if (!"".equals(path) && !path.endsWith("/")) { out.println("Parameter is not valid."); return; } // 目录不存在或不是目录 File currentPathFile = new File(currentPath); if (!currentPathFile.isDirectory()) { out.println("Directory does not exist."); return; } // 遍历目录取的文件信息 List<Hashtable> fileList = new ArrayList<Hashtable>(); if (currentPathFile.listFiles() != null) { for (File file : currentPathFile.listFiles()) { Hashtable<String, Object> hash = new Hashtable<String, Object>(); String fileName = file.getName(); if (file.isDirectory()) { hash.put("is_dir", true); hash.put("has_file", (file.listFiles() != null)); hash.put("filesize", 0L); hash.put("is_photo", false); hash.put("filetype", ""); } else if (file.isFile()) { String fileExt = fileName.substring( fileName.lastIndexOf(".") + 1).toLowerCase(); hash.put("is_dir", false); hash.put("has_file", false); hash.put("filesize", file.length()); hash.put("is_photo", Arrays.<String> asList(fileTypes) .contains(fileExt)); hash.put("filetype", fileExt); } hash.put("filename", fileName); hash.put("datetime", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(file .lastModified())); fileList.add(hash); } } if ("size".equals(order)) { Collections.sort(fileList, new SizeComparator()); } else if ("type".equals(order)) { Collections.sort(fileList, new TypeComparator()); } else { Collections.sort(fileList, new NameComparator()); } Map<String, Object> msg = new HashMap<String, Object>(); msg.put("moveup_dir_path", moveupDirPath); msg.put("current_dir_path", currentDirPath); msg.put("current_url", currentUrl); msg.put("total_count", fileList.size()); msg.put("file_list", fileList); response.setContentType("application/json; charset=UTF-8"); String msgStr = ""; msgStr = JSON.toJSONString(msg); out.println(msgStr); } @SuppressWarnings("rawtypes") class NameComparator implements Comparator { public int compare(Object a, Object b) { Hashtable hashA = (Hashtable) a; Hashtable hashB = (Hashtable) b; if (((Boolean) hashA.get("is_dir")) && !((Boolean) hashB.get("is_dir"))) { return -1; } else if (!((Boolean) hashA.get("is_dir")) && ((Boolean) hashB.get("is_dir"))) { return 1; } else { return ((String) hashA.get("filename")) .compareTo((String) hashB.get("filename")); } } } @SuppressWarnings("rawtypes") class SizeComparator implements Comparator { public int compare(Object a, Object b) { Hashtable hashA = (Hashtable) a; Hashtable hashB = (Hashtable) b; if (((Boolean) hashA.get("is_dir")) && !((Boolean) hashB.get("is_dir"))) { return -1; } else if (!((Boolean) hashA.get("is_dir")) && ((Boolean) hashB.get("is_dir"))) { return 1; } else { if (((Long) hashA.get("filesize")) > ((Long) hashB .get("filesize"))) { return 1; } else if (((Long) hashA.get("filesize")) < ((Long) hashB .get("filesize"))) { return -1; } else { return 0; } } } } @SuppressWarnings("rawtypes") class TypeComparator implements Comparator { public int compare(Object a, Object b) { Hashtable hashA = (Hashtable) a; Hashtable hashB = (Hashtable) b; if (((Boolean) hashA.get("is_dir")) && !((Boolean) hashB.get("is_dir"))) { return -1; } else if (!((Boolean) hashA.get("is_dir")) && ((Boolean) hashB.get("is_dir"))) { return 1; } else { return ((String) hashA.get("filetype")) .compareTo((String) hashB.get("filetype")); } } } }