ckeditor中“浏览服务器”的后台操作
此博文,基于CKeditor 4.5.6版本测试通过。
原创博文,转载请注明出处
参考官方文档,以及网络上的一些帖子。经过调试得到正确的期待中的结果。
【网络上的一些所谓的帖子,不知道是故意将上传的代码整点错误其中,还是无疑间遗漏了些什么,总之整个看是完整的程序,经过我的仔细研究和debug,存在很多KENG, 我崇尚分享的理念,既然blog出来,就要认真的对网友有所帮助】
这里,简单的贴一下ckeditor的配置:
CKEDITOR.editorConfig = function( config ) {
config.toolbarGroups = [
{ name: 'document', groups: [ 'mode', 'document', 'doctools' ] },
{ name: 'clipboard', groups: [ 'clipboard', 'undo' ] },
{ name: 'editing', groups: [ 'find', 'selection', 'spellchecker', 'editing' ] },
{ name: 'forms', groups: [ 'forms' ] },
'/',
{ name: 'basicstyles', groups: [ 'basicstyles', 'cleanup' ] },
{ name: 'paragraph', groups: [ 'list', 'indent', 'blocks', 'align', 'bidi', 'paragraph' ] },
{ name: 'links', groups: [ 'links' ] },
{ name: 'insert', groups: [ 'insert' ] },
'/',
{ name: 'styles', groups: [ 'styles' ] },
{ name: 'colors', groups: [ 'colors' ] },
{ name: 'tools', groups: [ 'tools' ] },
{ name: 'others', groups: [ 'others' ] }
]; config.removeButtons = 'Source,Save,NewPage,Scayt, About';
config.image_previewText=' '; //预览区域显示内容
config.filebrowserImageBrowseUrl = '/browse/mgmt?type=image';
config.filebrowserImageUploadUrl = '/upload/mgmt?type=image';
};
细心的朋友,可能会发现,这个和我前一篇博文有一点点不同,其实是为了让spring后台程序更加健壮而做了写重构所需的调整。不影响大局。
下面贴出后台的完整代码:
package com.tinguish.mueas.infra.upload; import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod; import com.tinguish.mueas.constant.FileType;
import com.tinguish.mueas.constant.MueasConstants; /**
* 浏览服务器的文件.
* 目标是做到让用户只能浏览自己曾经上传的问题,不能看别人的文件。
*
*/
@Controller
public class FileBrowerController {
protected final Logger logger = Logger.getLogger(getClass()); private static final String IMAGE_DIR = MueasConstants.FILE_UPLOAD_DIR + MueasConstants.FILE_UPLOAD_SUB_IMG_DIR; private static final String FILE_DIR = MueasConstants.FILE_UPLOAD_DIR + MueasConstants.FILE_UPLOAD_SUB_FILE_DIR; private static final String FLASH_DIR = MueasConstants.FILE_UPLOAD_DIR + MueasConstants.FILE_UPLOAD_SUB_FLASH_DIR; private static final String VIDEO_DIR = MueasConstants.FILE_UPLOAD_DIR + MueasConstants.FILE_UPLOAD_SUB_VIDEO_DIR; @RequestMapping(value = "/browse/mgmt", method = RequestMethod.GET)
public void processBrower(ModelMap modelMap, HttpServletRequest request,
HttpServletResponse response) {
logger.info(System.currentTimeMillis());
processBrowerPost(modelMap, request, response);
return;
} @SuppressWarnings("deprecation")
@RequestMapping(value = "/browse/mgmt", method = RequestMethod.POST)
public void processBrowerPost(ModelMap modelMap, HttpServletRequest request, HttpServletResponse response) { String typeStr = request.getParameter("type");
String floderName = request.getParameter("folder"); if (logger.isDebugEnabled()) {
logger.debug("Browsing files,format: " + typeStr);
} String realPath = "";
if(StringUtils.isNotBlank(floderName)){
floderName = URLDecoder.decode(floderName);
// 如果请求中存在文件夹名称,则定位到文件夹中
realPath = request.getSession().getServletContext().getRealPath(floderName);
if(logger.isInfoEnabled()){
logger.info("Requested folder:" + realPath);
}
}else if(StringUtils.equalsIgnoreCase(typeStr, FileType.IMAGE.name())){
// 如果请求中不存在文件夹名称,则使用默认的文件夹
realPath = request.getSession().getServletContext().getRealPath(MueasConstants.APP_RUNNING_FILES_DIR + IMAGE_DIR);
if(logger.isInfoEnabled()){
logger.info("Default folder:" + realPath);
}
} File folder = new File(realPath);
if(!folder.exists()){
return;
} // 存储子目录
List<String> subFolderSet = new ArrayList<String>();
// 存储文件夹
List<String> subFileerSet = new ArrayList<String>(); File[] subFiles = folder.listFiles();
if(null != subFiles && 0 < subFiles.length){
for(int i=0;i < subFiles.length; i++){
File _file = subFiles[i];
if(_file.isDirectory()){
subFolderSet.add(getDefaultFolderFromMueasRunningData(_file));
} else {
subFileerSet.add(getFileName(_file.getName()));
}
}
} String callback = request.getParameter("CKEditorFuncNum");
PrintWriter out; response.setContentType("text/html");
response.setCharacterEncoding("UTF-8");
String outs = "<!DOCTYPE html>"
+ "<html>"
+ "<head>"
+ "<title>服务器文件</title>"
+ "</head>"
+ "<body>";
try {
out = response.getWriter(); outs += "<style type='text/css'>"
+ "li:hover{"
+ " color: #34ac83;"
+ " font-size: 19px;"
+ " cursor: pointer;"
+ "}"
+ "</style>"; outs += "<script type='text/javascript'>"; // 定义点击选择js
String choose = "function choose(obj){"
+ "window.opener.CKEDITOR.tools.callFunction(" + callback + ", obj);"
+ "window.close();"
+"}";
outs += choose;
//logger.info(choose); // 定义文件夹点击响应js
String view = "function view(obj){"
+ "window.location.href='/browse/mgmt?type=image&CKEditorFuncNum=" + callback + "&folder=' + obj;"
+"}";
//logger.info(view);
outs += view;
outs +="</script>"; // 这里显示一个返回顶级目录,也就是返回mueas-running-data目录
String div1 = "<div style='width:100%;float:left;word-break:break-all;' "
+ "onclick =view('" + URLEncoder.encode(MueasConstants.APP_RUNNING_FILES_DIR + MueasConstants.FILE_UPLOAD_DIR) + "')>"
+ "<li>根级目录</li>"
+ "</div>";
//logger.info(div1);
outs += div1; // 如果是子文件夹,显示上级目录链接
if(StringUtils.isNotBlank(floderName) && !checkIsRoot(folder)){
String parent = getDefaultFolderFromMueasRunningData(folder.getParentFile());
String div2 = "<div style='width:100%;float:left;word-break:break-all;' onclick =view('" + URLEncoder.encode(parent) + "')>"
+ "<li>上级目录: "+parent+"</li>"
+ "</div>";
//logger.info(div2);
outs += div2;
if(logger.isDebugEnabled()){
logger.debug("Parent folder exists: " + parent);
}
} // 如果是文件夹,则显示文件夹并且可以再次触发下级和上级目录
if(0 < subFolderSet.size()){
Iterator<String> subFolderSetIndex = subFolderSet.iterator();
while(subFolderSetIndex.hasNext()){
String ftemp = subFolderSetIndex.next();
// 这里url传递的时候,需要转义
String div3 = "<div style='width:100%;float:left;word-break:break-all;' onclick =view('" + URLEncoder.encode(ftemp) + "')>"
+ "<li>下级目录: "+ftemp+"</li>"
+ "</div>";
//logger.info(div3);
outs += div3; if(logger.isDebugEnabled()){
logger.debug("Adding sub folder: "+ftemp);
}
}
} // 如果是文件,则点击就选择文件到控件中
if(0 < subFileerSet.size()){
Iterator<String> subFileerSetIndex = subFileerSet.iterator();
while(subFileerSetIndex.hasNext()){
String ftemp = subFileerSetIndex.next();
String f = getDefaultFolderFromMueasRunningData(folder);
String fileUrl = f + File.separator + ftemp;
fileUrl = StringUtils.replace(fileUrl, "//", "/");
String div4 = "<div style='width:150px;height:150px;float:left;word-break:break-all;padding:5px;background:#666699;margin:5px;'>"
+ "<a href='javascript:void(0)' onclick=choose('"+fileUrl+"')>"
+ "<img style='border:none;width:145px;height:145px;' src='"+fileUrl+"' title='"+fileUrl+"'/>"
+ "</a>"
+ "</div>";
//logger.info(div4);
outs += div4; if(logger.isDebugEnabled()){
logger.debug("Adding file: " + fileUrl);
}
}
}
outs += "</body></html>";
logger.info(outs);
out.println(outs);
out.flush();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
} /**
* 从/mueas-running-data这一级开始获取文件夹路径
* @return
*/
private static String getDefaultFolderFromMueasRunningData(File folder){
String path = folder.getPath();
path = path.substring(path.indexOf(MueasConstants.APP_RUNNING_FILES_DIR));
return path;
} /**
* 判断是否是根目录
* @param floderName
* @return
*/
private static boolean checkIsRoot(File folder){
String name = getFileName(folder.getName());
return StringUtils.equalsIgnoreCase("/" + name, MueasConstants.FILE_UPLOAD_DIR);
} /**
* 获取输入文件路径或者目录路径中最后一级的名字,即可能是一个文件名,也可能是一个子目录的名字
*
* @param file
* @return
*/
private static String getFileName(String file){
String temp = new String(file);
temp = temp.replace("//", "/");
String items[] = file.split("/");
if(items.length > 0){
return items[items.length - 1];
}else{
return null;
}
}
}
这其中,需要细心的是动态创建的html文件,我在这里遇到了些小问题,主要是字符串拼接时格式的问题。这些,通过打印日志,还是比较容易看出来的!
最后,上一下测试效果图片:
点击上面鼠标所在位置的子目录后,得到下面的图片:
欢迎拍砖。
ckeditor中“浏览服务器”的后台操作的更多相关文章
- ruby -- 进阶学习(十六)ckeditor去除“浏览服务器”按钮
FROM:http://blog.163.com/zjc_8886/blog/static/2408175201011222590967/ 实现方法: 由于ckeditor中的"上传图片& ...
- CKEditor禁用浏览服务器的功能
在CKeditor的config.js文件中,添加以下内容,重启服务器,图片.flash.video中的浏览服务器按钮就会消失掉 /*按下" 浏览服务器"按钮时应启动的外部文件管理 ...
- AngularJs调用NET MVC 控制器中的函数进行后台操作
题目中提到的控制器指的是.NET MVC的控制器,不是angularjs的控制器. 首先看主页面的代码: <!DOCTYPE html> <html> <head> ...
- MFC程序执行后台操作时不允许操作界面的一种方法
在使用MFC编写界面程序时,有时候会遇到像点击按钮后,后台进行大量操作后才显示处理结果这种情况,在后台处理过程中,界面不应该被允许做任何操作,这里介绍一种方法. 解决办法 点击按钮后,弹出一个模态对话 ...
- 通过使用Web Workers,Web应用程序可以在独立于主线程的后台线程中,运行一个脚本操作。这样做的好处是可以在独立线程中执行费时的处理任务,从而允许主线程(通常是UI线程)不会因此被阻塞/放慢。
Web Workers API - Web API 接口参考 | MDNhttps://developer.mozilla.org/zh-CN/docs/Web/API/Web_Workers_API ...
- CKEditor4.7怎样实现上传图片,浏览服务器(无需ckfinder),nodejs图片管理,字体居中,图片居中(超详细)
首先是下载CKEditor,下载地址:http://ckeditor.com/download 选择里面的Customize自定义,如图 然后进入配置界面,第一个choose preset一般就选st ...
- YII2 实现后台操作记录日志(转)
一.连接linux服务器,创建数据文件 php yii migrate/create user_log 二.修改数据文件 console/migrations/m150721_032220_admin ...
- atitit. web 在线文件管理器最佳实践(1)--- elFinder 的使用流程解决之道 。打开浏览服务器文件夹java .net php
atitit. web 在线文件管理器最佳实践(1)--- elFinder 的使用流程解决之道 .打开浏览服务器文件夹java .net php 1. 环境:::项目java web,需要打开浏览服 ...
- YII2 实现后台操作记录日志
一.连接linux服务器,创建数据文件 php yii migrate/create user_log 二.修改数据文件 console/migrations/m150721_032220_admin ...
随机推荐
- 第二个Sprint冲刺第十天
讨论地点:宿舍 讨论成员:邵家文.李新.朱浩龙.陈俊金
- select与epoll、apache与nginx实现原理对比
转自:http://www.tuicool.com/articles/AzmiY3 关于select与epoll 两种IO模型,都属于多路IO就绪通知,提供了对大量文件描述符就绪检查的高性能方案,只不 ...
- fsutil
编号:1035时间:2016年8月29日15:41:57功能:fsutil栗子:fsutil file createnew e:\b.txt 1073741824 //创建1G文件http://www ...
- CentOS安装时小坑记录
在安装CentOS的时候,由于第一次安装小白,将VM虚拟机的内存设置为512M,导致进行安装的时候无法进入正常的画面安装模式,只能使用简版安装界面,可能对于很多小白不是很熟悉,特此记录,安装CentO ...
- hdu 5206 Four Inages Strategy
题目大意: 判断空间上4个点是否形成一个正方形 分析: 标称思想 : 在p2,p3,p4中枚举两个点作为p1的邻点,不妨设为pi,pj,然后判断p1pi与p1pj是否相等.互相垂直,然后由向量法,最后 ...
- 更改SAP GUI 登陆背景
您也可以定制初始屏幕(SAP Easy Access): 所有用户的全局设置:o 更改位于初始屏幕右侧的登录 - 如果希望将登录放置在初始屏幕右侧,请按如下处理: 使用事务 SW ...
- 11. Container With Most Water
Given n non-negative integers a1, a2, ..., an, where each represents a point at coordinate (i, ai). ...
- ZOJ 1042 W’s Cipher
原题链接 题目大意:按照规则解码.26个字母分成三组,每一组按照顺时针移位编码.现在已知移动的位数,要求解码. 解法:以前看过一本古典密码学的书,百度贴吧密码吧也有很多经典的加密方法,想什么凯撒移位. ...
- leetcode 141. Linked List Cycle ----- java
Given a linked list, determine if it has a cycle in it. Follow up:Can you solve it without using ext ...
- leetcode 117 Populating Next Right Pointers in Each Node II ----- java
Follow up for problem "Populating Next Right Pointers in Each Node". What if the given tre ...