首页 > 代码库 > kindeditor Springmvc 整和解决图片上传问题
kindeditor Springmvc 整和解决图片上传问题
1. 在编辑页面引入js
<script type="text/javascript" charset="utf-8" src="http://www.mamicode.com/${basePath }/js/plugin/kindeditor-4.1.7/kindeditor-min.js"></script>
<script type="text/javascript" charset="utf-8" src="http://www.mamicode.com/${basePath }/js/plugin/kindeditor-4.1.7/lang/zh_CN.js"></script>
2.textarea绑定
<textarea name="content" class="common-textarea" id="content" style="width:100%; height:580px;visibility:hidden;"></textarea>
3.初始化插件
1 var editor = KindEditor.create(‘textarea[name="content"]‘, { 2 uploadJson : basePath + ‘/kindeditor/fileUpload‘, 3 fileManagerJson : basePath + ‘/kindeditor/fileManager‘, 4 allowFileManager : true, 5 items : [‘source‘, ‘|‘, ‘undo‘, ‘redo‘, ‘|‘, ‘preview‘, ‘template‘, ‘cut‘, ‘copy‘, ‘paste‘, 6 ‘plainpaste‘, ‘wordpaste‘, ‘|‘, ‘justifyleft‘, ‘justifycenter‘, ‘justifyright‘, 7 ‘justifyfull‘, ‘insertorderedlist‘, ‘insertunorderedlist‘, ‘indent‘, ‘outdent‘, ‘subscript‘, 8 ‘superscript‘, ‘clearhtml‘, ‘quickformat‘, ‘selectall‘, ‘|‘, ‘fullscreen‘, ‘/‘, 9 ‘formatblock‘, ‘fontname‘, ‘fontsize‘, ‘|‘, ‘forecolor‘, ‘hilitecolor‘, ‘bold‘, 10 ‘italic‘, ‘underline‘, ‘strikethrough‘, ‘lineheight‘, ‘removeformat‘, ‘|‘, ‘image‘,‘multiimage‘, 11 ‘flash‘, ‘media‘, ‘insertfile‘, ‘table‘, ‘hr‘, ‘emoticons‘, ‘baidumap‘, ‘pagebreak‘, 12 ‘anchor‘, ‘link‘, ‘unlink‘] 13 });
4.controller
1 import java.io.File; 2 import java.io.FileOutputStream; 3 import java.io.IOException; 4 import java.text.SimpleDateFormat; 5 import java.util.ArrayList; 6 import java.util.Arrays; 7 import java.util.Collections; 8 import java.util.Comparator; 9 import java.util.Date; 10 import java.util.HashMap; 11 import java.util.Hashtable; 12 import java.util.Iterator; 13 import java.util.List; 14 import java.util.Map; 15 import java.util.Random; 16 17 import javax.servlet.ServletContext; 18 import javax.servlet.ServletException; 19 import javax.servlet.ServletOutputStream; 20 import javax.servlet.http.HttpServletRequest; 21 import javax.servlet.http.HttpServletResponse; 22 23 import org.apache.commons.fileupload.FileItemFactory; 24 import org.apache.commons.fileupload.FileUploadException; 25 import org.apache.commons.fileupload.disk.DiskFileItemFactory; 26 import org.apache.commons.fileupload.servlet.ServletFileUpload; 27 import org.codehaus.jackson.map.ObjectMapper; 28 import org.springframework.stereotype.Controller; 29 import org.springframework.web.bind.annotation.RequestMapping; 30 import org.springframework.web.bind.annotation.RequestMethod; 31 import org.springframework.web.bind.annotation.ResponseBody; 32 import org.springframework.web.multipart.MultipartFile; 33 import org.springframework.web.multipart.MultipartHttpServletRequest; 34 35 import com.google.common.io.ByteStreams; 36 37 @Controller 38 @RequestMapping("kindeditor") 39 public class KindEditorController { 40 41 private static final ObjectMapper objectMapper = new ObjectMapper(); 42 43 @RequestMapping(value = "http://www.mamicode.com/fileUpload", method = RequestMethod.POST) 44 @ResponseBody 45 public Map<String, Object> fileUpload(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException, 46 FileUploadException { 47 ServletContext application = request.getSession().getServletContext(); 48 String savePath = application.getRealPath("/") + "images/"; 49 50 // 文件保存目录URL 51 String saveUrl = request.getContextPath() + "/images/"; 52 53 // 定义允许上传的文件扩展名 54 HashMap<String, String> extMap = new HashMap<String, String>(); 55 extMap.put("image", "gif,jpg,jpeg,png,bmp"); 56 extMap.put("flash", "swf,flv"); 57 extMap.put("media", "swf,flv,mp3,wav,wma,wmv,mid,avi,mpg,asf,rm,rmvb"); 58 extMap.put("file", "doc,docx,xls,xlsx,ppt,htm,html,txt,zip,rar,gz,bz2"); 59 60 // 最大文件大小 61 long maxSize = 1000000; 62 63 response.setContentType("text/html; charset=UTF-8"); 64 65 if (!ServletFileUpload.isMultipartContent(request)) { 66 return getError("请选择文件。"); 67 } 68 // 检查目录 69 File uploadDir = new File(savePath); 70 if (!uploadDir.isDirectory()) { 71 return getError("上传目录不存在。"); 72 } 73 // 检查目录写权限 74 if (!uploadDir.canWrite()) { 75 return getError("上传目录没有写权限。"); 76 } 77 78 String dirName = request.getParameter("dir"); 79 if (dirName == null) { 80 dirName = "image"; 81 } 82 if (!extMap.containsKey(dirName)) { 83 return getError("目录名不正确。"); 84 } 85 // 创建文件夹 86 savePath += dirName + "/"; 87 saveUrl += dirName + "/"; 88 File saveDirFile = new File(savePath); 89 if (!saveDirFile.exists()) { 90 saveDirFile.mkdirs(); 91 } 92 SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd"); 93 String ymd = sdf.format(new Date()); 94 savePath += ymd + "/"; 95 saveUrl += ymd + "/"; 96 File dirFile = new File(savePath); 97 if (!dirFile.exists()) { 98 dirFile.mkdirs(); 99 } 100 101 FileItemFactory factory = new DiskFileItemFactory(); 102 ServletFileUpload upload = new ServletFileUpload(factory); 103 upload.setHeaderEncoding("UTF-8"); 104 105 106 MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request; 107 108 Iterator item = multipartRequest.getFileNames(); 109 while (item.hasNext()) { 110 111 String fileName = (String) item.next(); 112 113 MultipartFile file = multipartRequest.getFile(fileName); 114 115 116 // 检查文件大小 117 118 if (file.getSize() > maxSize) { 119 120 return getError("上传文件大小超过限制。"); 121 122 } 123 124 // 检查扩展名 125 126 String fileExt = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".") + 1).toLowerCase(); 127 128 if (!Arrays. asList(extMap.get(dirName).split(",")).contains(fileExt)) { 129 return getError("上传文件扩展名是不允许的扩展名。\n只允许" 130 + extMap.get(dirName) + "格式。"); 131 132 } 133 SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss"); 134 135 String newFileName = df.format(new Date()) + "_" + new Random().nextInt(1000) + "." + fileExt; 136 137 try { 138 139 File uploadedFile = new File(savePath, newFileName); 140 141 ByteStreams.copy(file.getInputStream(), new FileOutputStream(uploadedFile)); 142 143 } catch (Exception e) { 144 145 return getError("上传文件失败。"); 146 147 } 148 Map<String, Object> msg = new HashMap<String, Object>(); 149 msg.put("error", 0); 150 msg.put("url", saveUrl + newFileName); 151 return msg; 152 } 153 return null; 154 } 155 156 private Map<String, Object> getError(String message) { 157 Map<String, Object> msg = new HashMap<String, Object>(); 158 msg.put("error", 1); 159 msg.put("message", message); 160 return msg; 161 } 162 163 @RequestMapping(value = "http://www.mamicode.com/fileManager", method = RequestMethod.POST) 164 public void fileManager(HttpServletRequest request, 165 HttpServletResponse response) throws ServletException, IOException { 166 ServletContext application = request.getSession().getServletContext(); 167 ServletOutputStream out = response.getOutputStream(); 168 // 根目录路径,可以指定绝对路径,比如 /var/www/attached/ 169 String rootPath = application.getRealPath("/") + "images/"; 170 // 根目录URL,可以指定绝对路径,比如 http://www.yoursite.com/attached/ 171 String rootUrl = request.getContextPath() + "/images/"; 172 // 图片扩展名 173 String[] fileTypes = new String[] { "gif", "jpg", "jpeg", "png", "bmp" }; 174 175 String dirName = request.getParameter("dir"); 176 if (dirName != null) { 177 if (!Arrays.<String> asList( 178 new String[] { "image", "flash", "media", "file" }) 179 .contains(dirName)) { 180 out.println("Invalid Directory name."); 181 return; 182 } 183 rootPath += dirName + "/"; 184 rootUrl += dirName + "/"; 185 File saveDirFile = new File(rootPath); 186 if (!saveDirFile.exists()) { 187 saveDirFile.mkdirs(); 188 } 189 } 190 // 根据path参数,设置各路径和URL 191 String path = request.getParameter("path") != null ? request 192 .getParameter("path") : ""; 193 String currentPath = rootPath + path; 194 String currentUrl = rootUrl + path; 195 String currentDirPath = path; 196 String moveupDirPath = ""; 197 if (!"".equals(path)) { 198 String str = currentDirPath.substring(0, 199 currentDirPath.length() - 1); 200 moveupDirPath = str.lastIndexOf("/") >= 0 ? str.substring(0, 201 str.lastIndexOf("/") + 1) : ""; 202 } 203 204 // 排序形式,name or size or type 205 String order = request.getParameter("order") != null ? request 206 .getParameter("order").toLowerCase() : "name"; 207 208 // 不允许使用..移动到上一级目录 209 if (path.indexOf("..") >= 0) { 210 out.println("Access is not allowed."); 211 return; 212 } 213 // 最后一个字符不是/ 214 if (!"".equals(path) && !path.endsWith("/")) { 215 out.println("Parameter is not valid."); 216 return; 217 } 218 // 目录不存在或不是目录 219 File currentPathFile = new File(currentPath); 220 if (!currentPathFile.isDirectory()) { 221 out.println("Directory does not exist."); 222 return; 223 } 224 // 遍历目录取的文件信息 225 List<Hashtable> fileList = new ArrayList<Hashtable>(); 226 if (currentPathFile.listFiles() != null) { 227 for (File file : currentPathFile.listFiles()) { 228 Hashtable<String, Object> hash = new Hashtable<String, Object>(); 229 String fileName = file.getName(); 230 if (file.isDirectory()) { 231 hash.put("is_dir", true); 232 hash.put("has_file", (file.listFiles() != null)); 233 hash.put("filesize", 0L); 234 hash.put("is_photo", false); 235 hash.put("filetype", ""); 236 } else if (file.isFile()) { 237 String fileExt = fileName.substring( 238 fileName.lastIndexOf(".") + 1).toLowerCase(); 239 hash.put("is_dir", false); 240 hash.put("has_file", false); 241 hash.put("filesize", file.length()); 242 hash.put("is_photo", Arrays.<String> asList(fileTypes) 243 .contains(fileExt)); 244 hash.put("filetype", fileExt); 245 } 246 hash.put("filename", fileName); 247 hash.put("datetime", 248 new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(file 249 .lastModified())); 250 fileList.add(hash); 251 } 252 } 253 254 if ("size".equals(order)) { 255 Collections.sort(fileList, new SizeComparator()); 256 } else if ("type".equals(order)) { 257 Collections.sort(fileList, new TypeComparator()); 258 } else { 259 Collections.sort(fileList, new NameComparator()); 260 } 261 Map<String, Object> msg = new HashMap<String, Object>(); 262 msg.put("moveup_dir_path", moveupDirPath); 263 msg.put("current_dir_path", currentDirPath); 264 msg.put("current_url", currentUrl); 265 msg.put("total_count", fileList.size()); 266 msg.put("file_list", fileList); 267 response.setContentType("application/json; charset=UTF-8"); 268 String msgStr = objectMapper.writeValueAsString(msg); 269 out.println(msgStr); 270 } 271 272 class NameComparator implements Comparator { 273 public int compare(Object a, Object b) { 274 Hashtable hashA = (Hashtable) a; 275 Hashtable hashB = (Hashtable) b; 276 if (((Boolean) hashA.get("is_dir")) 277 && !((Boolean) hashB.get("is_dir"))) { 278 return -1; 279 } else if (!((Boolean) hashA.get("is_dir")) 280 && ((Boolean) hashB.get("is_dir"))) { 281 return 1; 282 } else { 283 return ((String) hashA.get("filename")) 284 .compareTo((String) hashB.get("filename")); 285 } 286 } 287 } 288 289 class SizeComparator implements Comparator { 290 public int compare(Object a, Object b) { 291 Hashtable hashA = (Hashtable) a; 292 Hashtable hashB = (Hashtable) b; 293 if (((Boolean) hashA.get("is_dir")) 294 && !((Boolean) hashB.get("is_dir"))) { 295 return -1; 296 } else if (!((Boolean) hashA.get("is_dir")) 297 && ((Boolean) hashB.get("is_dir"))) { 298 return 1; 299 } else { 300 if (((Long) hashA.get("filesize")) > ((Long) hashB 301 .get("filesize"))) { 302 return 1; 303 } else if (((Long) hashA.get("filesize")) < ((Long) hashB 304 .get("filesize"))) { 305 return -1; 306 } else { 307 return 0; 308 } 309 } 310 } 311 } 312 313 class TypeComparator implements Comparator { 314 public int compare(Object a, Object b) { 315 Hashtable hashA = (Hashtable) a; 316 Hashtable hashB = (Hashtable) b; 317 if (((Boolean) hashA.get("is_dir")) 318 && !((Boolean) hashB.get("is_dir"))) { 319 return -1; 320 } else if (!((Boolean) hashA.get("is_dir")) 321 && ((Boolean) hashB.get("is_dir"))) { 322 return 1; 323 } else { 324 return ((String) hashA.get("filetype")) 325 .compareTo((String) hashB.get("filetype")); 326 } 327 } 328 } 329 330 }
注意点:
如果上传报错:
java.lang.ClassCastException: utn.app.servlet.XssMultipartHttpServletRequestWrapper cannot be cast to org.springframework.web.multipart.MultipartHttpServletRequest
at utn.aic.controller.KindEditorController.fileUpload(KindEditorController.java:108)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:137)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:747)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:676)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:938)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:870)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:961)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:863)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:648)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:837)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:292)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
at utn.aic.filter.XssFilter.doFilter(XssFilter.java:33)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:212)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:141)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:616)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:528)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1100)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:687)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1520)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1476)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
可能是受web.xml配置影响
<filter>
<filter-name>xssFilter</filter-name>
<filter-class>utn.aic.filter.XssFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>xssFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
注释掉即可;
kindeditor Springmvc 整和解决图片上传问题