[Java] CKEditor上传图片 服务端 →→→→→进入此内容的聊天室

来自 , 2019-08-21, 写在 Java, 查看 101 次.
URL http://www.code666.cn/view/288cc0ff
  1. package com.normandy.position.web;
  2.  
  3. import java.io.File;
  4. import java.io.IOException;
  5. import java.io.PrintWriter;
  6. import java.text.DateFormat;
  7. import java.text.ParseException;
  8. import java.text.SimpleDateFormat;
  9. import java.util.Date;
  10. import java.util.Iterator;
  11. import java.util.List;
  12.  
  13. import javax.servlet.http.HttpServletRequest;
  14. import javax.servlet.http.HttpServletResponse;
  15.  
  16. import org.apache.commons.fileupload.FileItem;
  17. import org.apache.commons.fileupload.FileItemFactory;
  18. import org.apache.commons.fileupload.FileUploadException;
  19. import org.apache.commons.fileupload.disk.DiskFileItemFactory;
  20. import org.apache.commons.fileupload.servlet.ServletFileUpload;
  21. import org.apache.commons.lang.StringUtils;
  22. import org.apache.commons.lang.time.DateUtils;
  23. import org.apache.log4j.Logger;
  24. import org.springframework.stereotype.Controller;
  25. import org.springframework.ui.ModelMap;
  26. import org.springframework.web.bind.annotation.RequestMapping;
  27. import org.springframework.web.bind.annotation.RequestMethod;
  28.  
  29. /**
  30.  * 上传图片
  31.  * <p>
  32.  *      为CKEDITOR定制的图片上传功能,后续可以扩展上传其他格式的文件
  33.  *  上传的文件的基础路径为: ${apache.home}/${project.name}/${project.name}/freemarker/upload/img/${'yyyyMMdd'}/
  34.  *  每个文件夹下最多500个文件
  35.  * </p>
  36.  * @author mikko
  37.  *
  38.  */
  39. @Controller
  40. @RequestMapping ("/upload.do")
  41. public class FileUploadController {
  42.     protected final Logger logger = Logger
  43.                                     .getLogger (FileUploadController.class);
  44.  
  45.     /** ~~~ 上传文件的保存路径 */
  46.     private static final String FILE_UPLOAD_DIR = "/upload";
  47.     /** ~~~ 上传文件的保存的下一级路径,标示存储类型 */
  48.     private static final String FILE_UPLOAD_SUB_IMG_DIR = "/img";
  49.     /** ~~~ 为了能让CKEDITOR加载到上传的图片,此处将位置限制在了freemarker下*/
  50.     private static final String FOR_FREEMARKER_LOAD_DIR = "/freemarker";
  51.     /** ~~~ 每个上传子目录保存的文件的最大数目 */
  52.     private static final int MAX_NUM_PER_UPLOAD_SUB_DIR = 500;
  53.     /** ~~~ 上传文件的最大文件大小 */
  54.     private static final long MAX_FILE_SIZE = 1024 * 1024 * 2;
  55.     /** ~~~ 系统默认建立和使用的以时间字符串作为文件名称的时间格式*/
  56.     private static final String DEFAULT_SUB_FOLDER_FORMAT_AUTO = "yyyyMMdd";
  57.     /** ~~~ 这里扩充一下格式,防止手动建立的不统一*/
  58.     private static final String DEFAULT_SUB_FOLDER_FORMAT_NO_AUTO = "yyyy-MM-dd";
  59.  
  60.     @RequestMapping (method = RequestMethod.GET)
  61.     public void processUpload (ModelMap modelMap, HttpServletRequest request,
  62.                                HttpServletResponse response) {
  63.         processUploadPost (modelMap, request, response);
  64.         return;
  65.     }
  66.  
  67.     @RequestMapping (method = RequestMethod.POST)
  68.     public void processUploadPost (ModelMap modelMap,
  69.                                    HttpServletRequest request, HttpServletResponse response) {
  70.  
  71.         // 判断提交的请求是否包含文件
  72.         boolean isMultipart = ServletFileUpload.isMultipartContent (request);
  73.  
  74.         if (!isMultipart) {
  75.             return;
  76.         }
  77.  
  78.         // 获取目录
  79.         File floder = buildFolder (request);
  80.         if (null == floder) {
  81.             return;
  82.         }
  83.  
  84.         try {
  85.             response.setContentType ("text/html; charset=UTF-8");
  86.             response.setHeader ("Cache-Control", "no-cache");
  87.             PrintWriter out = response.getWriter();
  88.             // 上传文件的返回地址
  89.             String fileUrl = "";
  90.  
  91.             FileItemFactory factory = new DiskFileItemFactory();
  92.  
  93.             ServletFileUpload servletFileUpload = new ServletFileUpload (factory);
  94.             servletFileUpload.setFileSizeMax (MAX_FILE_SIZE);
  95.  
  96.             @SuppressWarnings ("unchecked")
  97.             List<FileItem> fileitem = servletFileUpload.parseRequest (request);
  98.  
  99.             if (null == fileitem || 0 == fileitem.size() ) {
  100.                 return;
  101.             }
  102.  
  103.             Iterator<FileItem> fileitemIndex = fileitem.iterator();
  104.             if (fileitemIndex.hasNext() ) {
  105.                 FileItem file = fileitemIndex.next();
  106.  
  107.                 if (file.isFormField() ) {
  108.                     logger.error ("上传文件非法!isFormField=true");
  109.                 }
  110.  
  111.                 String fileClientName = getFileName (file.getName() );
  112.                 String fileFix = StringUtils.substring (fileClientName,
  113.                                                         fileClientName.lastIndexOf (".") + 1);
  114.                 if (!StringUtils.equalsIgnoreCase (fileFix, "jpg")
  115.                         && !StringUtils.equalsIgnoreCase (fileFix, "jpeg")
  116.                         && !StringUtils.equalsIgnoreCase (fileFix, "bmp")
  117.                         && !StringUtils.equalsIgnoreCase (fileFix, "gif")
  118.                         && !StringUtils.equalsIgnoreCase (fileFix, "png") ) {
  119.                     logger.error ("上传文件的格式错误=" + fileFix);
  120.                     return;
  121.                 }
  122.  
  123.                 if (logger.isInfoEnabled() ) {
  124.                     logger.info ("开始上传文件:" + file.getName() );
  125.                 }
  126.  
  127.                 // 为了客户端已经设置好了图片名称在服务器继续能够明确识别,这里不改名称
  128.                 File newfile = new File (floder, fileClientName);
  129.                 file.write (newfile);
  130.  
  131.                 if (logger.isInfoEnabled() ) {
  132.                     logger.info ("上传文件结束,新名称:" + fileClientName + ".floder:"
  133.                                  + newfile.getPath() );
  134.                 }
  135.  
  136.                 // 组装返回url,以便于ckeditor定位图片
  137.                 fileUrl = FOR_FREEMARKER_LOAD_DIR + FILE_UPLOAD_DIR + FILE_UPLOAD_SUB_IMG_DIR + File.separator + floder.getName() + File.separator + newfile.getName();
  138.                 fileUrl = fileUrl.substring (1); // 去掉/freemarker的第一个/,否则ckeditor不识别
  139.                 fileUrl = StringUtils.replace (fileUrl, "//", "/");
  140.  
  141.                 // 将上传的图片的url返回给ckeditor
  142.                 String callback = request.getParameter ("CKEditorFuncNum");
  143.                 out.println ("<mce:script type=/"text / javascript / "><!--
  144.                             ");
  145.                 out.println ("window.parent.CKEDITOR.tools.callFunction("
  146.                              + callback + ",'" + fileUrl + "',''" + ")");
  147.                 out.println ("
  148.                             // --></mce:script>");
  149.             }
  150.  
  151.             out.flush();
  152.             out.close();
  153.  
  154.         } catch (IOException e) {
  155.             logger.error ("上传文件发生异常!", e);
  156.         } catch (FileUploadException e) {
  157.             logger.error ("上传文件发生异常!", e);
  158.         } catch (Exception e) {
  159.             logger.error ("上传文件发生异常!", e);
  160.         }
  161.  
  162.         return;
  163.     }
  164.  
  165.     /**
  166.      * 获取文件名称
  167.      * @param str
  168.      * @return
  169.      */
  170.     private String getFileName (String str) {
  171.         int index = str.lastIndexOf ("//");
  172.         if (-1 != index) {
  173.             return str.substring (index);
  174.         } else {
  175.             return str;
  176.         }
  177.     }
  178.  
  179.     /**
  180.      * 创建目录
  181.      *
  182.      * @return
  183.      */
  184.     private File buildFolder (HttpServletRequest request) {
  185.         // 这里照顾一下CKEDITOR,由于ftl放置位置的原因,这里必须要在freemarker目录下才能被加载到图片,否则虽然可以正常上传和使用,但是
  186.         // 在控件中无法正常操作
  187.         String realPath = request.getSession().getServletContext()
  188.                           .getRealPath (FOR_FREEMARKER_LOAD_DIR);
  189.  
  190.         logger.error (realPath);
  191.  
  192.         // 一级目录,如果不存在,创建
  193.         File firstFolder = new File (realPath + FILE_UPLOAD_DIR);
  194.         if (!firstFolder.exists() ) {
  195.             if (!firstFolder.mkdir() ) {
  196.                 return null;
  197.             }
  198.         }
  199.  
  200.         // 二级目录,如果不存在,创建
  201.         String folderdir = realPath + FILE_UPLOAD_DIR + FILE_UPLOAD_SUB_IMG_DIR;
  202.         if (logger.isDebugEnabled() ) {
  203.             logger.debug ("folderdir" + folderdir);
  204.         }
  205.  
  206.         if (StringUtils.isBlank (folderdir) ) {
  207.             logger.error ("路径错误:" + folderdir);
  208.             return null;
  209.         }
  210.  
  211.         File floder = new File (folderdir);
  212.         if (!floder.exists() ) {
  213.             if (!floder.mkdir() ) {
  214.                 logger.error ("创建文件夹出错!path=" + folderdir);
  215.                 return null;
  216.             }
  217.  
  218.         }
  219.         // 再往下的文件夹都是以时间字符串来命名的,所以获取最新时间的文件夹即可
  220.         String[] files = floder.list();
  221.         if (null != files && 0 < files.length) {
  222.             // 含有子文件夹,则获取最新的一个
  223.             Date oldDate = null;
  224.             int index = -1;
  225.             for (int i = 0; i < files.length; i++) {
  226.                 String fileName = files[i];
  227.  
  228.                 try {
  229.                     Date thisDate = DateUtils.parseDate (fileName, new String[] {
  230.                         DEFAULT_SUB_FOLDER_FORMAT_AUTO, DEFAULT_SUB_FOLDER_FORMAT_NO_AUTO
  231.                     });
  232.                     if (oldDate == null) {
  233.                         oldDate = thisDate;
  234.                         index = i;
  235.                     } else {
  236.                         if (thisDate.after (oldDate) ) {
  237.                             // 保存最新的时间和数组中的下标
  238.                             oldDate = thisDate;
  239.                             index = i;
  240.                         }
  241.                     }
  242.                 } catch (ParseException e) {
  243.                     // 这里异常吃掉,不用做什么,如果解析失败,会建立新的文件夹,防止人为的建立文件夹导致的异常。
  244.                 }
  245.             }// for
  246.  
  247.             // 判断当前最新的文件夹下是否已经存在了最大数目的图片
  248.             if (null != oldDate && -1 != index) {
  249.                 File pointfloder = new File (folderdir + File.separator
  250.                                              + files[index]);
  251.                 if (!pointfloder.exists() ) {
  252.                     if (!pointfloder.mkdir() ) {
  253.                         logger.error ("创建文件夹出错!path=" + folderdir);
  254.                         return null;
  255.                     }
  256.                 }
  257.  
  258.                 // 如果文件夹下的文件超过了最大值,那么也需要新建一个文件夹
  259.                 String[] pointfloderFiles = pointfloder.list();
  260.                 if (null != pointfloderFiles
  261.                         && MAX_NUM_PER_UPLOAD_SUB_DIR < pointfloderFiles.length) {
  262.                     return buildNewFile (folderdir);
  263.                 }
  264.  
  265.                 return pointfloder;
  266.             }
  267.  
  268.             // 查找当前子文件夹失败,新建一个
  269.             return buildNewFile (folderdir);
  270.         } else {
  271.             // 不含有子文件夹,新建一个,通常系统首次上传会有这个情况
  272.             return buildNewFile (folderdir);
  273.         }
  274.  
  275.     }
  276.  
  277.     /**
  278.      * 创建一个新文件
  279.      * @param path
  280.      * @return
  281.      */
  282.     private File buildNewFile (String path) {
  283.         // 不含有子文件夹,新建一个,通常系统首次上传会有这个情况
  284.         File newFile = buildFileBySysTime (path);
  285.         if (null == newFile) {
  286.             logger.error ("创建文件夹失败!newFile=" + newFile);
  287.         }
  288.  
  289.         return newFile;
  290.     }
  291.  
  292.     /**
  293.      * 根据当前的时间建立文件夹,时间格式yyyyMMdd
  294.      *
  295.      * @param path
  296.      * @return
  297.      */
  298.     private File buildFileBySysTime (String path) {
  299.         DateFormat df = new SimpleDateFormat (DEFAULT_SUB_FOLDER_FORMAT_AUTO);
  300.         String fileName = df.format (new Date() );
  301.         File file = new File (path + File.separator + fileName);
  302.         if (!file.mkdir() ) {
  303.             return null;
  304.         }
  305.         return file;
  306.     }
  307. }

回复 "CKEditor上传图片 服务端"

这儿你可以回复上面这条便签

captcha