首页 > 代码库 > 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 整和解决图片上传问题