此博文,基于CKeditor 4.5.6版本测试通过。
原创博文,转载请注明出处
参考官方文档,以及网络上的一些帖子。经过调试得到正确的期待中的结果。
【网络上的一些所谓的帖子,不知道是故意将上传的代码整点错误其中,还是无疑间遗漏了些什么,总之整个看是完整的程序,经过我的仔细研究和debug,存在很多KENG, 我崇尚分享的理念,既然blog出来,就要认真的对网友有所帮助】
这里,简单的贴一下ckeditor的配置:
1 CKEDITOR.editorConfig = function( config ) { 2 config.toolbarGroups = [ 3 { name: 'document', groups: [ 'mode', 'document', 'doctools' ] }, 4 { name: 'clipboard', groups: [ 'clipboard', 'undo' ] }, 5 { name: 'editing', groups: [ 'find', 'selection', 'spellchecker', 'editing' ] }, 6 { name: 'forms', groups: [ 'forms' ] }, 7 '/', 8 { name: 'basicstyles', groups: [ 'basicstyles', 'cleanup' ] }, 9 { name: 'paragraph', groups: [ 'list', 'indent', 'blocks', 'align', 'bidi', 'paragraph' ] }, 10 { name: 'links', groups: [ 'links' ] }, 11 { name: 'insert', groups: [ 'insert' ] }, 12 '/', 13 { name: 'styles', groups: [ 'styles' ] }, 14 { name: 'colors', groups: [ 'colors' ] }, 15 { name: 'tools', groups: [ 'tools' ] }, 16 { name: 'others', groups: [ 'others' ] } 17 ]; 18 19 config.removeButtons = 'Source,Save,NewPage,Scayt, About'; 20 config.image_previewText=' '; //预览区域显示内容 21 config.filebrowserImageBrowseUrl = '/browse/mgmt?type=image'; 22 config.filebrowserImageUploadUrl = '/upload/mgmt?type=image'; 23 };
细心的朋友,可能会发现,这个和我前一篇博文有一点点不同,其实是为了让spring后台程序更加健壮而做了写重构所需的调整。不影响大局。
下面贴出后台的完整代码:
1 package com.tinguish.mueas.infra.upload; 2 3 import java.io.File; 4 import java.io.IOException; 5 import java.io.PrintWriter; 6 import java.net.URLDecoder; 7 import java.net.URLEncoder; 8 import java.util.ArrayList; 9 import java.util.Iterator; 10 import java.util.List; 11 12 import javax.servlet.http.HttpServletRequest; 13 import javax.servlet.http.HttpServletResponse; 14 15 import org.apache.commons.lang3.StringUtils; 16 import org.apache.log4j.Logger; 17 import org.springframework.stereotype.Controller; 18 import org.springframework.ui.ModelMap; 19 import org.springframework.web.bind.annotation.RequestMapping; 20 import org.springframework.web.bind.annotation.RequestMethod; 21 22 import com.tinguish.mueas.constant.FileType; 23 import com.tinguish.mueas.constant.MueasConstants; 24 25 /** 26 * 浏览服务器的文件. 27 * 目标是做到让用户只能浏览自己曾经上传的问题,不能看别人的文件。 28 * 29 */ 30 @Controller 31 public class FileBrowerController { 32 protected final Logger logger = Logger.getLogger(getClass()); 33 34 private static final String IMAGE_DIR = MueasConstants.FILE_UPLOAD_DIR + MueasConstants.FILE_UPLOAD_SUB_IMG_DIR; 35 36 private static final String FILE_DIR = MueasConstants.FILE_UPLOAD_DIR + MueasConstants.FILE_UPLOAD_SUB_FILE_DIR; 37 38 private static final String FLASH_DIR = MueasConstants.FILE_UPLOAD_DIR + MueasConstants.FILE_UPLOAD_SUB_FLASH_DIR; 39 40 private static final String VIDEO_DIR = MueasConstants.FILE_UPLOAD_DIR + MueasConstants.FILE_UPLOAD_SUB_VIDEO_DIR; 41 42 43 @RequestMapping(value = "/browse/mgmt", method = RequestMethod.GET) 44 public void processBrower(ModelMap modelMap, HttpServletRequest request, 45 HttpServletResponse response) { 46 logger.info(System.currentTimeMillis()); 47 processBrowerPost(modelMap, request, response); 48 return; 49 } 50 51 @SuppressWarnings("deprecation") 52 @RequestMapping(value = "/browse/mgmt", method = RequestMethod.POST) 53 public void processBrowerPost(ModelMap modelMap, HttpServletRequest request, HttpServletResponse response) { 54 55 String typeStr = request.getParameter("type"); 56 String floderName = request.getParameter("folder"); 57 58 if (logger.isDebugEnabled()) { 59 logger.debug("Browsing files,format: " + typeStr); 60 } 61 62 63 String realPath = ""; 64 if(StringUtils.isNotBlank(floderName)){ 65 floderName = URLDecoder.decode(floderName); 66 // 如果请求中存在文件夹名称,则定位到文件夹中 67 realPath = request.getSession().getServletContext().getRealPath(floderName); 68 if(logger.isInfoEnabled()){ 69 logger.info("Requested folder:" + realPath); 70 } 71 }else if(StringUtils.equalsIgnoreCase(typeStr, FileType.IMAGE.name())){ 72 // 如果请求中不存在文件夹名称,则使用默认的文件夹 73 realPath = request.getSession().getServletContext().getRealPath(MueasConstants.APP_RUNNING_FILES_DIR + IMAGE_DIR); 74 if(logger.isInfoEnabled()){ 75 logger.info("Default folder:" + realPath); 76 } 77 } 78 79 File folder = new File(realPath); 80 if(!folder.exists()){ 81 return; 82 } 83 84 // 存储子目录 85 List<String> subFolderSet = new ArrayList<String>(); 86 // 存储文件夹 87 List<String> subFileerSet = new ArrayList<String>(); 88 89 File[] subFiles = folder.listFiles(); 90 if(null != subFiles && 0 < subFiles.length){ 91 for(int i=0;i < subFiles.length; i++){ 92 File _file = subFiles[i]; 93 if(_file.isDirectory()){ 94 subFolderSet.add(getDefaultFolderFromMueasRunningData(_file)); 95 } else { 96 subFileerSet.add(getFileName(_file.getName())); 97 } 98 } 99 } 100 101 String callback = request.getParameter("CKEditorFuncNum"); 102 PrintWriter out; 103 104 response.setContentType("text/html"); 105 response.setCharacterEncoding("UTF-8"); 106 String outs = "<!DOCTYPE html>" 107 + "<html>" 108 + "<head>" 109 + "<title>服务器文件</title>" 110 + "</head>" 111 + "<body>"; 112 try { 113 out = response.getWriter(); 114 115 outs += "<style type='text/css'>" 116 + "li:hover{" 117 + " color: #34ac83;" 118 + " font-size: 19px;" 119 + " cursor: pointer;" 120 + "}" 121 + "</style>"; 122 123 outs += "<script type='text/javascript'>"; 124 125 // 定义点击选择js 126 String choose = "function choose(obj){" 127 + "window.opener.CKEDITOR.tools.callFunction(" + callback + ", obj);" 128 + "window.close();" 129 +"}"; 130 outs += choose; 131 //logger.info(choose); 132 133 // 定义文件夹点击响应js 134 String view = "function view(obj){" 135 + "window.location.href='/browse/mgmt?type=image&CKEditorFuncNum=" + callback + "&folder=' + obj;" 136 +"}"; 137 //logger.info(view); 138 outs += view; 139 outs +="</script>"; 140 141 // 这里显示一个返回顶级目录,也就是返回mueas-running-data目录 142 String div1 = "<div style='100%;float:left;word-break:break-all;' " 143 + "onclick =view('" + URLEncoder.encode(MueasConstants.APP_RUNNING_FILES_DIR + MueasConstants.FILE_UPLOAD_DIR) + "')>" 144 + "<li>根级目录</li>" 145 + "</div>"; 146 //logger.info(div1); 147 outs += div1; 148 149 // 如果是子文件夹,显示上级目录链接 150 if(StringUtils.isNotBlank(floderName) && !checkIsRoot(folder)){ 151 String parent = getDefaultFolderFromMueasRunningData(folder.getParentFile()); 152 String div2 = "<div style='100%;float:left;word-break:break-all;' onclick =view('" + URLEncoder.encode(parent) + "')>" 153 + "<li>上级目录: "+parent+"</li>" 154 + "</div>"; 155 //logger.info(div2); 156 outs += div2; 157 if(logger.isDebugEnabled()){ 158 logger.debug("Parent folder exists: " + parent); 159 } 160 } 161 162 // 如果是文件夹,则显示文件夹并且可以再次触发下级和上级目录 163 if(0 < subFolderSet.size()){ 164 Iterator<String> subFolderSetIndex = subFolderSet.iterator(); 165 while(subFolderSetIndex.hasNext()){ 166 String ftemp = subFolderSetIndex.next(); 167 // 这里url传递的时候,需要转义 168 String div3 = "<div style='100%;float:left;word-break:break-all;' onclick =view('" + URLEncoder.encode(ftemp) + "')>" 169 + "<li>下级目录: "+ftemp+"</li>" 170 + "</div>"; 171 //logger.info(div3); 172 outs += div3; 173 174 if(logger.isDebugEnabled()){ 175 logger.debug("Adding sub folder: "+ftemp); 176 } 177 } 178 } 179 180 // 如果是文件,则点击就选择文件到控件中 181 if(0 < subFileerSet.size()){ 182 Iterator<String> subFileerSetIndex = subFileerSet.iterator(); 183 while(subFileerSetIndex.hasNext()){ 184 String ftemp = subFileerSetIndex.next(); 185 String f = getDefaultFolderFromMueasRunningData(folder); 186 String fileUrl = f + File.separator + ftemp; 187 fileUrl = StringUtils.replace(fileUrl, "//", "/"); 188 String div4 = "<div style='150px;height:150px;float:left;word-break:break-all;padding:5px;background:#666699;margin:5px;'>" 189 + "<a href='javascript:void(0)' onclick=choose('"+fileUrl+"')>" 190 + "<img style='border:none;145px;height:145px;' src='"+fileUrl+"' title='"+fileUrl+"'/>" 191 + "</a>" 192 + "</div>"; 193 //logger.info(div4); 194 outs += div4; 195 196 if(logger.isDebugEnabled()){ 197 logger.debug("Adding file: " + fileUrl); 198 } 199 } 200 } 201 outs += "</body></html>"; 202 logger.info(outs); 203 out.println(outs); 204 out.flush(); 205 out.close(); 206 } catch (IOException e) { 207 e.printStackTrace(); 208 } 209 } 210 211 /** 212 * 从/mueas-running-data这一级开始获取文件夹路径 213 * @return 214 */ 215 private static String getDefaultFolderFromMueasRunningData(File folder){ 216 String path = folder.getPath(); 217 path = path.substring(path.indexOf(MueasConstants.APP_RUNNING_FILES_DIR)); 218 return path; 219 } 220 221 /** 222 * 判断是否是根目录 223 * @param floderName 224 * @return 225 */ 226 private static boolean checkIsRoot(File folder){ 227 String name = getFileName(folder.getName()); 228 return StringUtils.equalsIgnoreCase("/" + name, MueasConstants.FILE_UPLOAD_DIR); 229 } 230 231 /** 232 * 获取输入文件路径或者目录路径中最后一级的名字,即可能是一个文件名,也可能是一个子目录的名字 233 * 234 * @param file 235 * @return 236 */ 237 private static String getFileName(String file){ 238 String temp = new String(file); 239 temp = temp.replace("//", "/"); 240 String items[] = file.split("/"); 241 if(items.length > 0){ 242 return items[items.length - 1]; 243 }else{ 244 return null; 245 } 246 } 247 }
这其中,需要细心的是动态创建的html文件,我在这里遇到了些小问题,主要是字符串拼接时格式的问题。这些,通过打印日志,还是比较容易看出来的!
最后,上一下测试效果图片:
点击上面鼠标所在位置的子目录后,得到下面的图片:
欢迎拍砖。