简介
轻量级的富文本编辑器,配置简单,功能丰富,相对于百度的ueditor配置简单不少,
自定义上传文件接口方便,实用
官方地址
引入到项目
-
项目结构
-
项目介绍
将下载好的kindEditor包放在webapp下,我这里放在了static/kindeditor下
- jsp引入kindeditor
标记的部分是要引入到页面里的,设置textarea的id,
kindeditor初始化的要用到。
- kindeditor初始化
/**
* kindEditor初始化
* @returns
*/
function kindEditorInit(){
return kindEditorInitp('80%','400px','#editor_id');
}
/**
* kindEditor初始化
* @param width 宽
* @param height 高
* @param editorId 对应的textarea的id
*/
function kindEditorInitp(width,height,editorId){
var editor = KindEditor.create(editorId, {
themeType : 'default',//主题样式,在theme文件夹里
langType : 'zh-CN',//中文
width : width,//宽,也可以是px
height: height,//高,不可以是px
items: [//工具栏
'source', '|', 'undo', 'redo', '|', 'preview', 'print', 'template', 'code', 'cut', 'copy', 'paste',
'plainpaste', 'wordpaste', '|', 'justifyleft', 'justifycenter', 'justifyright',
'justifyfull', 'insertorderedlist', 'insertunorderedlist', 'indent', 'outdent', 'subscript',
'superscript', 'clearhtml', 'quickformat', 'selectall', '|', 'fullscreen', '/',
'formatblock', 'fontname', 'fontsize', '|', 'forecolor', 'hilitecolor', 'bold',
'italic', 'underline', 'strikethrough', 'lineheight', 'removeformat', '|', 'image', 'multiimage',
'flash', 'media', 'insertfile', 'table', 'hr', 'emoticons', 'baidumap', 'pagebreak',
'anchor', 'link', 'unlink'
],
fontSizeTable: ['6px','9px', '10px', '12px', '14px', '16px', '18px', '24px', '32px'],//字体大小
uploadJson : '../upload-kind-editor',//图片上传
fileManagerJson : '../file-manager',//图片管理
allowFileManager : true
});
return editor;
}
/**
* 获取kindeditor的内容
* @param editor
* @returns
*/
function getKindEditorHtml(editor){
return html = editor.html();
}
/**
* 设置kindEditor的内容
* @param editor
* @param html 内容
*/
function setKindEditorHtml(editor,html){
editor.html(html);
}
我这里封装成了一个单独的js,里面写了初始化已经获取和设置编辑器的内容,
相关的配置可以参考官方的文档介绍,这里就介绍上传图片和图片管理的接口。
- uploadJson图片上传
/**
* kindeditor上传图片
* @param tf
* @return
* @throws IOException
* @throws UploadException
*/
@SuppressWarnings("deprecation")
@At("/upload-kind-editor")
@Ok("json")
@AdaptBy(type = UploadAdaptor.class)
public NutMap uploadKindEditor(@Param("imgFile") TempFile tf) throws IOException, UploadException{
NutMap rv = new NutMap();
try {
File file = tf.getFile(); // 这个是保存的临时文件
FieldMeta meta = tf.getMeta(); // 这个原本的文件信息
String oldName = meta.getFileLocalName(); // 这个时原本的文件名称
String contentType = meta.getContentType();
log.info("contentType:"+contentType);
String suffix = "";
Long length = file.length();
log.info("file byte:"+length+" byte" +" and " + file.length()/1024/1024 +" M");
// if(AdminConstants.IMAGE_CONTENT_TYPE.containsKey(contentType)){
// suffix = AdminConstants.IMAGE_CONTENT_TYPE.get(contentType);
// }else{
// throw new BusinessException("文件格式不正确,请选择图片!");
// }
suffix = oldName.substring(oldName.indexOf("."),oldName.length());
log.info("suffix:"+suffix);
log.info("oldName:"+oldName);
log.info("file length:"+file.length());
log.info("fileName:"+file.getName());
String datePath = loadDatePath();
log.info("datePath:"+datePath);
String uploadPath = loadRealpath("/uploads/"+datePath);
log.info("uploadPath:"+uploadPath);
File dirFile = new File(uploadPath);
if(!dirFile.exists()){
dirFile.mkdirs();
}
String fileName = MyUtils.randomKey(32);
String path = uploadPath + "/" +fileName+suffix;
File newFile = new File(path);
FileUtils.copyFile(file, newFile);
String pathUrl = super.loadUrl()+ "/uploads/" + datePath + "/"+fileName+suffix;
Files f = new Files();
f.setContent(FileUtils.readFileToByteArray(file));
f.setContentType(contentType);
f.setFileName(oldName);
f.setPath(datePath+"/"+fileName+suffix);
f.setPathUrl(pathUrl);
f.setLength(length);
f.setSize(MyUtils.loadFileSize(length));
f = super.filesService.add(f);
String url = super.loadContextPath()+"/show-image/"+f.getId();
rv.put("error", 0);
rv.put("url", url);
} catch (BusinessException e){
rv.put("error", 1);
rv.put("message", e.getMessage());
} catch (Exception e) {
rv.put("error", 1);
rv.put("message", "系统异常!");
}
log.info("rv:"+rv.toString());
return rv;
}
后台用的java编写,框架是nutz,要注意的是kindeditor上传图片的name是imgFile,
即:<input type="file" name="imgFile" /> ,这样就可以直接获取到上传图片的
内容,返回值是:
//成功时
{
"error" : 0,
"url" : "http://www.example.com/path/to/file.ext"
}
//失败时
{
"error" : 1,
"message" : "错误信息"
}
- fileManagerJson图片管理
/**
* kindeditor的图片管理
* @return
*/
@At("/file-manager")
@Ok("json")
public NutMap fileManager(@Param("path")String path,@Param("order")String order,@Param("dir")String dir){
NutMap rv = new NutMap();
try {
log.info("path:"+path);
log.info("order:"+order);
log.info("dir:"+dir);
String rootPath = super.loadRealpath("/uploads/");
if(StringUtils.isEmpty(path)){
path = rootPath;
}
// 根目录URL,可以指定绝对路径,比如 http://www.yoursite.com/attached/
String rootUrl = rootPath;
// 遍历目录取的文件信息
List<Map<String, Object>> fileList = new ArrayList<Map<String, Object>>();
// 当前上传目录
File currentPathFile = new File(path);
// 图片扩展名
String[] fileTypes = new String[] { "gif", "jpg", "jpeg", "png", "bmp" };
Boolean fileFlag = false;
String fileUrl = null;
if (currentPathFile.listFiles() != null) {
for (File file : currentPathFile.listFiles()) {
Map<String, Object> hash = new HashMap<String, Object>();
String fileName = file.getName();
log.info("是目录:"+file.isDirectory());
log.info("是文件:"+file.isFile());
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 tmp = path.substring(path.length() - 9 ,path.length() - 1);
fileUrl = super.loadUrl() + "/uploads/" + tmp + "/";
fileFlag = true;
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);
}
}
log.info("fileFlag:"+fileFlag);
log.info("fileUrl:"+fileUrl);
Map<String, Object> result = new HashMap<String, Object>();
result.put("moveup_dir_path", "");
result.put("current_dir_path", fileFlag ? fileUrl : path+"\\");
result.put("current_url", fileFlag ? fileUrl : rootUrl+"\\");
result.put("total_count", fileList.size());
result.put("file_list", fileList);
rv = new NutMap(result);
log.info(rv.toString());
return rv;
} catch (BusinessException e){
rv.put("error", 1);
rv.put("message", e.getMessage());
} catch (Exception e) {
e.printStackTrace();
rv.put("error", 1);
rv.put("message", "系统异常!");
}
log.info("rv:"+rv.toString());
return rv;
}
这个接口要返回的是项目的实际路径,有一点需要注意的是,保存图片的时候最多两级,
比如:webapp/uploads/20180609/xxx.png,最多两级,要不然展示不出来,最后一级的
展示图片的那个current_url的返回值不能是真是路径,要是可以访问到图片的路径,
一级的访问json如下:
{
current_url = E: \javaProgram\ tcm\ trunk\ code\ src\ main\ webapp % uploads\, current_dir_path = E: \javaProgram\ tcm\ trunk\ code\ src\ main\ webapp % uploads\, moveup_dir_path = , file_list = [{
filesize = 0,
filename = 20180609,
filetype = ,
has_file = true,
is_photo = false,
datetime = 2018 - 06 - 09 12: 52: 15,
is_dir = true
}], total_count = 1
}
二级的访问json如下:
{
current_url = http: //jay.tohours.com/tcm/uploads/20180609/,
current_dir_path=http://jay.tohours.com/tcm/uploads/20180609/,
moveup_dir_path=,
file_list=[
{filesize=62721, filename=909ccifko3zxprv8ccx6bzriot65lxwq.jpg, filetype=jpg, has_file=false, is_photo=true, datetime=2018-06-09 12:52:15, is_dir=false},
{filesize=21516, filename=g5rtzny15mp328b908b2z65exd99tk8w.jpg, filetype=jpg, has_file=false, is_photo=true, datetime=2018-06-09 12:52:15, is_dir=false},
{filesize=610349, filename=no3i99vcascyjudugow39fny1nqddmb9.gif, filetype=gif, has_file=false, is_photo=true, datetime=2018-06-09 12:52:14, is_dir=false},
{filesize=156038, filename=plz755wueafpky6ytsx15ezxj45itv22.jpg, filetype=jpg, has_file=false, is_photo=true, datetime=2018-06-09 12:52:15, is_dir=false}],
total_count=4
}
- 整体显示效果
- fileManagerJson图片管理
/**
* kindeditor的图片管理
* @return
*/
@At("/file-manager")
@Ok("json")
public NutMap fileManager(@Param("path")String path,@Param("order")String order,@Param("dir")String dir){
NutMap rv = new NutMap();
try {
log.info("path:"+path);
log.info("order:"+order);
log.info("dir:"+dir);
String rootPath = super.loadRealpath("/uploads/");
if(StringUtils.isEmpty(path)){
path = rootPath;
}
// 根目录URL,可以指定绝对路径,比如 http://www.yoursite.com/attached/
String rootUrl = rootPath;
// 遍历目录取的文件信息
List<Map<String, Object>> fileList = new ArrayList<Map<String, Object>>();
// 当前上传目录
File currentPathFile = new File(path);
// 图片扩展名
String[] fileTypes = new String[] { "gif", "jpg", "jpeg", "png", "bmp" };
Boolean fileFlag = false;
String fileUrl = null;
if (currentPathFile.listFiles() != null) {
for (File file : currentPathFile.listFiles()) {
Map<String, Object> hash = new HashMap<String, Object>();
String fileName = file.getName();
log.info("是目录:"+file.isDirectory());
log.info("是文件:"+file.isFile());
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 tmp = path.substring(path.length() - 9 ,path.length() - 1);
fileUrl = super.loadUrl() + "/uploads/" + tmp + "/";
fileFlag = true;
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);
}
}
log.info("fileFlag:"+fileFlag);
log.info("fileUrl:"+fileUrl);
Map<String, Object> result = new HashMap<String, Object>();
result.put("moveup_dir_path", "");
result.put("current_dir_path", fileFlag ? fileUrl : path+"\\");
result.put("current_url", fileFlag ? fileUrl : rootUrl+"\\");
result.put("total_count", fileList.size());
result.put("file_list", fileList);
rv = new NutMap(result);
log.info(rv.toString());
return rv;
} catch (BusinessException e){
rv.put("error", 1);
rv.put("message", e.getMessage());
} catch (Exception e) {
e.printStackTrace();
rv.put("error", 1);
rv.put("message", "系统异常!");
}
log.info("rv:"+rv.toString());
return rv;
}
这个接口要返回的是项目的实际路径,有一点需要注意的是,保存图片的时候最多两级,
比如:webapp/uploads/20180609/xxx.png,最多两级,要不然展示不出来,最后一级的
展示图片的那个current_url的返回值不能是真是路径,要是可以访问到图片的路径,
一级的访问json如下:
{
current_url = E: \javaProgram\ tcm\ trunk\ code\ src\ main\ webapp % uploads\, current_dir_path = E: \javaProgram\ tcm\ trunk\ code\ src\ main\ webapp % uploads\, moveup_dir_path = , file_list = [{
filesize = 0,
filename = 20180609,
filetype = ,
has_file = true,
is_photo = false,
datetime = 2018 - 06 - 09 12: 52: 15,
is_dir = true
}], total_count = 1
}
二级的访问json如下:
{
current_url = http: //jay.tohours.com/tcm/uploads/20180609/,
current_dir_path=http://jay.tohours.com/tcm/uploads/20180609/,
moveup_dir_path=,
file_list=[
{filesize=62721, filename=909ccifko3zxprv8ccx6bzriot65lxwq.jpg, filetype=jpg, has_file=false, is_photo=true, datetime=2018-06-09 12:52:15, is_dir=false},
{filesize=21516, filename=g5rtzny15mp328b908b2z65exd99tk8w.jpg, filetype=jpg, has_file=false, is_photo=true, datetime=2018-06-09 12:52:15, is_dir=false},
{filesize=610349, filename=no3i99vcascyjudugow39fny1nqddmb9.gif, filetype=gif, has_file=false, is_photo=true, datetime=2018-06-09 12:52:14, is_dir=false},
{filesize=156038, filename=plz755wueafpky6ytsx15ezxj45itv22.jpg, filetype=jpg, has_file=false, is_photo=true, datetime=2018-06-09 12:52:15, is_dir=false}],
total_count=4
}
- 整体显示效果