web/easyui/ssm框架引用KindEditor富文本编辑器
KindEditor 是一套开源的在线HTML编辑器,主要用于让用户在网站上获得所见即所得编辑效果,开发人员可以用 KindEditor 把传统的多行文本输入框(textarea)替换为可视化的富文本输入框。
KindEditor 使用 JavaScript 编写,可以无缝地与 Java、.NET、PHP、ASP 等程序集成,比较适合在 CMS、商城、论坛、博客、Wiki、电子邮件等互联网应用上使用。
主要特点:
- 快速:体积小,加载速度快
- 开源:开放源代码,高水平,高品质
- 底层:内置自定义 DOM 类库,精确操作 DOM
- 扩展:基于插件的设计,所有功能都是插件,可根据需求增减功能
- 风格:修改编辑器风格非常容易,只需修改一个 CSS 文件
- 兼容:支持大部分主流浏览器,比如 IE、Firefox、Safari、Chrome、Opera
为什么使用KindEditor而不是经常提到的ueditor百度编辑器?
因为个人认为体积小,加载速度快,最主要的是,一般来说引用文本编辑器都只是需要文本编辑功能,其他杂七杂八的功能实际上太多了反而不好看。
其次就是遮罩层问题,初始化和对象销毁的问题,图片上传配置,官方jar包也有问题(貌似官方在mavne仓库没有jar包)。对于页面功能来说也没有特别大的改动,但是真正使用起来还是觉得KindEditor更加简便一些(这是个人观点),于是个人喜好使用KindEditor。
废话不多说,赶紧看实战。
2.web项目中集成KindEditor
-
下载编辑器
下载 KindEditor 最新版本,下载之后打开 examples/index.html 就可以看到演示。
下载页面: 下载地址 -
部署编辑器
解压 kindeditor-x.x.x.zip 文件,将所有文件上传到web程序目录里。
你可以根据开发需求,而删除以下目录后上传到服务器。(就是剔除不要的文件夹。)
asp - ASP程
asp.net - ASP.NET程序
php - PHP程序
jsp - JSP程序
examples - 演示文件
比如我的:
- 修改HTML页面
3.1 引用js文件:
3.2 在需要显示编辑器的位置添加textarea输入框。
<textarea id="editor" name="newscontent" placeholder="请输入文章内容..." style="width: 700px; height: 500px; ">
</textarea>
如图:
注意:
- id在当前页面必须是唯一的值。
- 在textarea里设置HTML内容即可实现编辑,在这里需要注意的是,如果从服务器端程序(ASP、PHP、ASP.NET等)直接显示内容,则必须转换HTML特殊字符(>,<,&,”)。具体请参考各语言目录下面的demo.xxx程序,目前支持ASP、ASP.NET、PHP、JSP。
- 在有些浏览器上不设宽度和高度可能显示有问题,所以最好设一下宽度和高度。宽度和高度可用inline样式设置,也可用 编辑器初始化参数 设置。
3.3 在该HTML页面添加以下脚本。
//KindEditor编辑器创建
KindEditor.ready(function (K) {
var editor;
/* 这个id要和textarea的id一致*/
window.editor = K.create('#editor',{
//指定的文件上传input的的属性名
filePostName: "uploadFile",
//批量/上传图片的控制
uploadJson: 'kindeditor/upload',
resizeType: 1, //滚动条
filterMode:false, //关闭过滤功能
allowPreviewEmoticons: true,
allowImageUpload: true,
fullscreenMode:false, //是否全屏
allowMediaUpload:false, //true时显示视音频上传按钮。默认值: true
allowFlashUpload:false, //true时显示Flash上传按钮;默认值: true
//编辑器宽度
width: '700px',
//加入以下行,后台就可以得到值
afterChange: function(){ //编辑器内容发生变化后,将编辑器的内容设置到原来的textarea控件里
this.sync(); },
afterBlur : function(){ //编辑器聚焦后,将编辑器的内容设置到原来的textarea控件里
this.sync(); }
});
})
如图:
- 更多设置参数:参数设置
关于编辑器当中的图片上传接收后台:
KindEditorUpload.java
源代码:
package com.hangtu.controller;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import com.alibaba.fastjson.JSONObject;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.*;
/**
*
*@class_name:KindEditorUpload
*@comments: 设置kindEditor上传图片路径
*@param:图片
*@return: url路径
*@author:邹涛/Zoutao
*@createtime:2018年9月25日
*/
@SuppressWarnings("serial")
@WebServlet("/kindeditor/upload")
public class KindEditorUpload extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//设置Response响应的编码
resp.setContentType("text/html; charset=UTF-8");
//获取一个Response的Write对象
PrintWriter writer = resp.getWriter();
//文件保存目录路径
String savePath = req.getServletContext().getRealPath("/") + "attached/";
System.out.println(savePath);
//文件保存目录URL
String saveUrl = req.getContextPath() + "/attached/";
System.out.print(saveUrl);
//定义允许上传的文件扩展名
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,txt,zip,rar,gz,bz2");
//最大文件大小
long maxSize = 1000000;
//判断是否是一个文件
if (!ServletFileUpload.isMultipartContent(req)) {
writer.println(getError("请选择文件。"));
return;
}
//检查目录
File uploadDir = new File(savePath);
if (!uploadDir.isDirectory()) {
writer.println(getError("上传目录不存在。"));
return;
}
//检查目录写权限
if (!uploadDir.canWrite()) {
writer.println(getError("上传目录没有写权限。"));
return;
}
String dirName = req.getParameter("dir");
if (dirName == null) {
dirName = "image";
}
if (!extMap.containsKey(dirName)) {
writer.println(getError("目录名不正确。"));
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 = null;
try {
items = upload.parseRequest(req);
} catch (FileUploadException e) {
e.printStackTrace();
}
Iterator itr = items.iterator();
while (itr.hasNext()) {
FileItem item = (FileItem) itr.next();
String fileName = item.getName();
long fileSize = item.getSize();
if (!item.isFormField()) {
//检查文件大小
if (item.getSize() > maxSize) {
writer.println(getError("上传文件大小超过限制。"));
return;
}
//检查扩展名
String fileExt = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
if (!Arrays.<String>asList(extMap.get(dirName).split(",")).contains(fileExt)) {
writer.println(getError("上传文件扩展名是不允许的扩展名。\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) {
writer.println(getError("上传文件失败。"));
return;
}
JSONObject obj = new JSONObject();
obj.put("error", 0);
obj.put("url", saveUrl + newFileName);
writer.println(obj.toJSONString());
}
}
//将writer对象中的内容输出
writer.flush();
//关闭writer对象
writer.close();
}
//私有方法,用于响应错误信息。
private String getError(String message) {
JSONObject obj = new JSONObject();
obj.put("error", 1);
obj.put("message", message);
return obj.toJSONString();
}
}
3.4. 获取HTML数据
注意,添加一行这个 就可以得到数据
afterBlur: function () { this.sync(); },
当失去焦点时执行 this.sync();,不加就获取不了文本框的值。
必须加有这个属性,这样后台才能取到编辑器里面写的内容。
如图:
- KindEditor的可视化操作在新创建的iframe上执行,代码模式下的textarea框也是新创建的,所以最后提交前需要执行 sync() 将HTML数据设置到原来的textarea。
- KindEditor在默认情况下自动寻找textarea所属的form元素,找到form后onsubmit事件里添加sync函数,所以用form方式提交数据,不需要手动执行sync()函数。
- KindEditor默认采用白名单过滤方式,可用 htmlTags 参数定义要保留的标签和属性。当然也可以用 filterMode 参数关闭过滤模式,保留所有标签。
// 关闭过滤模式,保留所有标签
KindEditor.options.filterMode = false;
KindEditor.ready(function(K)) {
K.create('#editor_id');
}
3.5 后台接收编辑器的文本值:
String newscontent = request.getParameter("newscontent"); //内容
就是个字符串获取即可,整个编辑器的内容,是封装在textarea里面的,也就是直接获取这个textarea的id就可以拿到编辑器里面的值。
效果图:
总结:
- 引用了KindEditor富文本编辑器,可以编辑文本信息
- 添加了图片上传功能在编辑器里面,可以上传图片。
- 后台可以存入html标签的编辑器的内容,包括图片。
3.相关难点
难点一:
关于 this.sync() 函数简单的说就是同步KindEditor的值到textarea文本域的问题?
KindEditor 从数据库里取值样式不正常的问题?
如图:
原因:可能是存在自动转义或者编辑器有过滤html的功能。
解决:实际上有没有样式是不影响的编辑器的内容显示的:
或者是这样
也就是无论你存那种值都是可以的,如果你想要单独的只在数据库中存入文字。那么就开启过滤标签的功能。开启和关闭的方式在上面 过滤模式的那里。
难点二:
在编辑文章的时候,KindEditor编辑器中没有内容?或者是获取不到内容?或者是编辑器里面的内容仍然是上一次添加的文章时的信息等等问题:
如图:
解决:
- 保证加入了 sync()函数。(参考上面)
- 然后在点击关闭窗口时,调用函数,清空值。
就可以解决这个问题。
参考地址:
http://www.cnblogs.com/jimisun/p/9408120.html
http://kindeditor.net/doc.php
https://www.cnblogs.com/libo0125ok/p/8127049.html