CKEditor 3安装和使用 & 自定义的Servlet实现CKEditor3的上传功能

FCKEditor是一款优秀的富文本编辑器,在Web开发中用作文本编辑插件,非常好用,现在已经升级为CKEditor3,界面更加炫酷,功能更加丰富。 
    之前在FCK中使用过文件上传功能(普通文件,图片,FLASH),而在CK中,官方使用另外一套组件CKFinder进行上传,CKFinder也是富客户端界面,效果不错,但是官方示例中没有对Java进行支持(PHP,ASP/ASP.NET都有)。改造CKFinder比较麻烦了,把PHP/.NET的改成Java的几乎不现实,还是等官网出java版本再使用吧。不过要是用CKEditor的上传功能没有关系,既然提供了上传接口,那么实现手段我们自己实现就是了,下面从CKEditor的安装开始介绍。 
    要使用CKEditor,首先要下载开发包,官网http://ckeditor.com/ 提供最新版下载,下载后包含源码和例子,当然正式运行中并不需要这些东西。我们可以提取如下内容: 
 
    ckeditor/lang下是语言支持包,这里可以精简,一般保留zh-cn和en就够了,目录放好后,就是配置和写页面了,也很简单。文件上传我们使用servlet进行,比较简单,只需要apache commons组件中的fileupload和io即可完成。 
    和FCKEditor不同的是,CKEditor的配置需要使用config.js。那我们先来配置config.js。 
Js代码    收藏代码
  1. CKEDITOR.editorConfig = function(config) {  
  2.     config.language = 'zh-cn'// 配置语言  
  3.     config.uiColor = '#FFF'// 背景颜色  
  4.     config.width = 'auto'// 宽度  
  5.     config.height = '300px'// 高度  
  6.     config.skin = 'office2003';//界面v2,kama,office2003  
  7.     config.toolbar = 'Full';// 工具栏风格Full,Basic  
  8. };  

    一般配置这些参数就够了,其他的详细配置可以参考文档了,值得说的是skin选项,有3中,v2就是还原到FCKEditor的风格,kama和office2003是新风格,我使用了office2003风格,官网的样式是kama。配置了skin后就不用配置uiColor了。下面看页面配置: 
Html代码    收藏代码
  1. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">  
  2. <html xmlns="http://www.w3.org/1999/xhtml">  
  3. <head>  
  4. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />  
  5. <script type="text/javascript" src="/ckeditor/ckeditor/ckeditor.js"></script>  
  6. <style type="text/css">  
  7. * {  
  8.     font-family: "宋体";  
  9.     font-size: 14px  
  10. }  
  11. </style>  
  12. <title>CKEditor</title>  
  13. </head>  
  14. <body>  
  15. <form id="form1" name="form1" method="post" action="/ckeditor/display.jsp">  
  16. <table width="650" height="400" border="0" align="center">  
  17.     <tr>  
  18.         <td valign="top">内容:</td>  
  19.         <td><textarea cols="80" id="content" name="content">  
  20.       </textarea> <script type="text/javascript">  
  21.         CKEDITOR.replace('content');  
  22. </script></td>  
  23.     </tr>  
  24.     <tr>  
  25.         <td></td>  
  26.         <td><input type="submit" name="Submit" value="提交" /> <input  
  27.             type="reset" name="Reset" value="重置" /></td>  
  28.     </tr>  
  29. </table>  
  30. </form>  
  31. </body>  
  32. </html>  

    引入js文件,注意相对路径不能错了,我这里工程名和文件夹同名,肯定出现两次。在HTML页面中写一个textarea,然后脚本段就完成了。配置非常简单,此时就可以看到CKEditor的效果了。但是打开图片,Flash时是没有上传选项卡的。 
    首先我们来测试一下CKEditor,写个JSP页面来接收参数即可 
Html代码    收藏代码
  1. <%@page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>  
  2. <html>  
  3. <head>  
  4. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">  
  5. <title>Display Content</title>  
  6. </head>  
  7. <%request.setCharacterEncoding("UTF-8"); %>  
  8. <center>  
  9. <table width="600" border="0" bordercolor="000000"  
  10.     style="table-layout: fixed;">  
  11.     <tr>  
  12.         <td width="100" bordercolor="ffffff">主题:</td>  
  13.         <td width="500" bordercolor="ffffff">${param.title}</td>  
  14.     </tr>  
  15.     <tr>  
  16.         <td valign="top" bordercolor="ffffff">内容:</td>  
  17.         <td valign="top" bordercolor="ffffff">${param.content}</td>  
  18.     </tr>  
  19. </table>  
  20. </center>  
  21. </html>  

 
    提交这个页面到display.jsp,我们就能看到下面的效果了,非常不错。 
 
    至此,CKEditor的安装和测试全部结束,我们已经得到想要的结果了,在系统设计时要考虑使用编辑器的数据库字段大小,要足够大。如果是发布系统那就使用freemarker模板生成静态文件保存吧。数据库设计还是不要挂太大的存储负载。 

   下面将介绍使用自定义的Servlet实现CKEditor3的上传功能。


 在CKEditor中把上传配置给打开,很简单,脚本段改为如下设置: 

Js代码    收藏代码
  1. <script type="text/javascript">  
  2.         CKEDITOR.replace('content',{filebrowserUploadUrl : '/ckeditor/ckeditor/uploader?Type=File',  
  3. filebrowserImageUploadUrl : '/ckeditor/ckeditor/uploader?Type=Image',  
  4. filebrowserFlashUploadUrl : '/ckeditor/ckeditor/uploader?Type=Flash'  
  5.         });  
  6. </script>  

    这里参数我们可以自己设置,加个Type为了区分文件类型,因为都使用同一个Servlet处理。事情没有这么简单,CKEditor毕竟是个复杂的组件,我们这么配置,看看它给我们还原成什么了吧,在FireFox中使用FireBug查看,看到了这些: 
 
    看到了吧,在Type后面它为我们又挂接了几个参数,其中我们需要的是CKEditorFuncNum和file域的name值upload,CKEditorFuncNum这个参数是用来回调页面的,就是上传成功后,页面自动切换到“图像”选项卡。upload参数是servlet获取上传文件用的参数名。其余参数就根据需要进行了。 
    这些参数的名称都是查看源码获得的,不能想当然。有了这些东西后面就好办了,就是文件上传了么。很简单了。这里我们使用apache commons组件中的fileupload和io。 
先看web.xml,我们做些设置。 
Xml代码    收藏代码
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"  
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee   
  5.     http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">  
  6.   
  7.     <servlet>  
  8.         <servlet-name>SimpleUploader</servlet-name>  
  9.         <servlet-class>ckeditor.CKEditorUploadServlet</servlet-class>  
  10.         <init-param>  
  11.             <param-name>baseDir</param-name>  
  12.             <param-value>/UserFiles/</param-value>  
  13.         </init-param>  
  14.         <init-param>  
  15.             <param-name>debug</param-name>  
  16.             <param-value>false</param-value>  
  17.         </init-param>  
  18.         <init-param>  
  19.             <param-name>enabled</param-name>  
  20.             <param-value>true</param-value>  
  21.         </init-param>  
  22.         <init-param>  
  23.             <param-name>AllowedExtensionsFile</param-name>  
  24.             <param-value></param-value>  
  25.         </init-param>  
  26.         <init-param>  
  27.             <param-name>DeniedExtensionsFile</param-name>  
  28.             <param-value>  
  29.                 html|htm|php|php2|php3|php4|php5|phtml|pwml|inc|asp|aspx|ascx|jsp|cfm|cfc|pl|bat|exe|com|dll|vbs|js|reg|cgi|htaccess|asis|ftl  
  30.             </param-value>  
  31.         </init-param>  
  32.         <init-param>  
  33.             <param-name>AllowedExtensionsImage</param-name>  
  34.             <param-value>jpg|gif|jpeg|png|bmp</param-value>  
  35.         </init-param>  
  36.         <init-param>  
  37.             <param-name>DeniedExtensionsImage</param-name>  
  38.             <param-value></param-value>  
  39.         </init-param>  
  40.         <init-param>  
  41.             <param-name>AllowedExtensionsFlash</param-name>  
  42.             <param-value>swf|fla</param-value>  
  43.         </init-param>  
  44.         <init-param>  
  45.             <param-name>DeniedExtensionsFlash</param-name>  
  46.             <param-value></param-value>  
  47.         </init-param>  
  48.         <load-on-startup>0</load-on-startup>  
  49.     </servlet>  
  50.   
  51.     <servlet-mapping>  
  52.         <servlet-name>SimpleUploader</servlet-name>  
  53.         <url-pattern>/ckeditor/uploader</url-pattern>  
  54.     </servlet-mapping>  
  55.   
  56.     <welcome-file-list>  
  57.         <welcome-file>index.html</welcome-file>  
  58.     </welcome-file-list>  
  59. </web-app>  

    主要是Servlet的初始化参数,规定了文件上传的扩展名规则,就是允许上传的类型和阻止上传的类型。分为File,Image和FLASH三种,这个上传参数的设置是对应的。Debug是设置servlet知否进行debug,默认是关闭的。enabled是设置该servlet是否有效,如果禁止上传,就打成false。还有一个baseDir是设定CKEditor上传文件的存放位置。 
    下面就是实现类了,比较长,但是有详细的注释: 
Java代码    收藏代码
  1. package ckeditor;  
  2. import java.io.*;  
  3. import java.text.SimpleDateFormat;  
  4. import java.util.*;  
  5. import javax.servlet.ServletException;  
  6. import javax.servlet.http.*;  
  7. import org.apache.commons.fileupload.FileItem;  
  8. import org.apache.commons.fileupload.FileItemFactory;  
  9. import org.apache.commons.fileupload.disk.DiskFileItemFactory;  
  10. import org.apache.commons.fileupload.servlet.ServletFileUpload;  
  11. public class CKEditorUploadServlet extends HttpServlet {  
  12.     private static String baseDir;// CKEditor的根目录  
  13.     private static boolean debug = false;// 是否debug模式  
  14.     private static boolean enabled = false;// 是否开启CKEditor上传  
  15.     private static Hashtable allowedExtensions;// 允许的上传文件扩展名  
  16.     private static Hashtable deniedExtensions;// 阻止的上传文件扩展名  
  17.     private static SimpleDateFormat dirFormatter;// 目录命名格式:yyyyMM  
  18.     private static SimpleDateFormat fileFormatter;// 文件命名格式:yyyyMMddHHmmssSSS  
  19.     /** 
  20.      * Servlet初始化方法 
  21.      */  
  22.     public void init() throws ServletException {  
  23.         // 从web.xml中读取debug模式  
  24.         debug = (new Boolean(getInitParameter("debug"))).booleanValue();  
  25.         if (debug)  
  26.             System.out  
  27.                     .println("\r\n---- SimpleUploaderServlet initialization started ----");  
  28.         // 格式化目录和文件命名方式  
  29.         dirFormatter = new SimpleDateFormat("yyyyMM");  
  30.         fileFormatter = new SimpleDateFormat("yyyyMMddHHmmssSSS");  
  31.         // 从web.xml中获取根目录名称  
  32.         baseDir = getInitParameter("baseDir");  
  33.         // 从web.xml中获取是否可以进行文件上传  
  34.         enabled = (new Boolean(getInitParameter("enabled"))).booleanValue();  
  35.         if (baseDir == null)  
  36.             baseDir = "/UserFiles/";  
  37.         String realBaseDir = getServletContext().getRealPath(baseDir);  
  38.         File baseFile = new File(realBaseDir);  
  39.         if (!baseFile.exists()) {  
  40.             baseFile.mkdirs();  
  41.         }  
  42.         // 实例化允许的扩展名和阻止的扩展名  
  43.         allowedExtensions = new Hashtable(3);  
  44.         deniedExtensions = new Hashtable(3);  
  45.         // 从web.xml中读取配置信息  
  46.         allowedExtensions.put("File",  
  47.         stringToArrayList(getInitParameter("AllowedExtensionsFile")));  
  48.         deniedExtensions.put("File",  
  49.         stringToArrayList(getInitParameter("DeniedExtensionsFile")));  
  50.         allowedExtensions.put("Image",  
  51.     stringToArrayList(getInitParameter("AllowedExtensionsImage")));  
  52.         deniedExtensions.put("Image",           stringToArrayList(getInitParameter("DeniedExtensionsImage")));  
  53.         allowedExtensions.put("Flash",          stringToArrayList(getInitParameter("AllowedExtensionsFlash")));  
  54.         deniedExtensions.put("Flash",           stringToArrayList(getInitParameter("DeniedExtensionsFlash")));  
  55.         if (debug)  
  56.             System.out  
  57.                     .println("---- SimpleUploaderServlet initialization completed ----\r\n");  
  58.     }  
  59.     public void doGet(HttpServletRequest request, HttpServletResponse response)  
  60.             throws ServletException, IOException {  
  61.         doPost(request, response);  
  62.     }  
  63.     public void doPost(HttpServletRequest request, HttpServletResponse response)  
  64.             throws ServletException, IOException {  
  65.         if (debug)  
  66.             System.out.println("--- BEGIN DOPOST ---");  
  67.         response.setContentType("text/html; charset=UTF-8");  
  68.         response.setHeader("Cache-Control""no-cache");  
  69.         PrintWriter out = response.getWriter();  
  70.         // 从请求参数中获取上传文件的类型:File/Image/Flash  
  71.         String typeStr = request.getParameter("Type");  
  72.         if (typeStr == null) {  
  73.             typeStr = "File";  
  74.         }  
  75.         if (debug)  
  76.             System.out.println(typeStr);  
  77.         // 实例化dNow对象,获取当前时间  
  78.         Date dNow = new Date();  
  79.         // 设定上传文件路径  
  80.         String currentPath = baseDir + typeStr + "/"  
  81.                 + dirFormatter.format(dNow);  
  82.         // 获得web应用的上传路径  
  83.         String currentDirPath = getServletContext().getRealPath(currentPath);  
  84.         // 判断文件夹是否存在,不存在则创建  
  85.         File dirTest = new File(currentDirPath);  
  86.         if (!dirTest.exists()) {  
  87.             dirTest.mkdirs();  
  88.         }  
  89.         // 将路径前加上web应用名  
  90.         currentPath = request.getContextPath() + currentPath;  
  91.         if (debug)  
  92.             System.out.println(currentDirPath);  
  93.         // 文件名和文件真实路径  
  94.         String newName = "";  
  95.         String fileUrl = "";  
  96.         if (enabled) {  
  97.             // 使用Apache Common组件中的fileupload进行文件上传  
  98.             FileItemFactory factory = new DiskFileItemFactory();  
  99.             ServletFileUpload upload = new ServletFileUpload(factory);  
  100.             try {  
  101.                 List items = upload.parseRequest(request);  
  102.                 Map fields = new HashMap();  
  103.                 Iterator iter = items.iterator();  
  104.                 while (iter.hasNext()) {  
  105.                     FileItem item = (FileItem) iter.next();  
  106.                     if (item.isFormField())  
  107.                         fields.put(item.getFieldName(), item.getString());  
  108.                     else  
  109.                         fields.put(item.getFieldName(), item);  
  110.                 }  
  111.                 // CEKditor中file域的name值是upload  
  112.                 FileItem uplFile = (FileItem) fields.get("upload");  
  113.                 // 获取文件名并做处理  
  114.                 String fileNameLong = uplFile.getName();  
  115.                 fileNameLong = fileNameLong.replace('\\', '/');  
  116.                 String[] pathParts = fileNameLong.split("/");  
  117.                 String fileName = pathParts[pathParts.length - 1];  
  118.                 // 获取文件扩展名  
  119.                 String ext = getExtension(fileName);  
  120.                 // 设置上传文件名  
  121.                 fileName = fileFormatter.format(dNow) + "." + ext;  
  122.                 // 获取文件名(无扩展名)  
  123.                 String nameWithoutExt = getNameWithoutExtension(fileName);  
  124.                 File pathToSave = new File(currentDirPath, fileName);  
  125.                 fileUrl = currentPath + "/" + fileName;  
  126.                 if (extIsAllowed(typeStr, ext)) {  
  127.                     int counter = 1;  
  128.                     while (pathToSave.exists()) {  
  129.                         newName = nameWithoutExt + "_" + counter + "." + ext;  
  130.                         fileUrl = currentPath + "/" + newName;  
  131.                         pathToSave = new File(currentDirPath, newName);  
  132.                         counter++;  
  133.                     }  
  134.                     uplFile.write(pathToSave);  
  135.                 } else {  
  136.                     if (debug)  
  137.                         System.out.println("无效的文件类型: " + ext);  
  138.                 }  
  139.             } catch (Exception ex) {  
  140.                 if (debug)  
  141.                     ex.printStackTrace();  
  142.             }  
  143.         } else {  
  144.             if (debug)  
  145.                 System.out.println("未开启CKEditor上传功能");  
  146.         }  
  147.         // CKEditorFuncNum是回调时显示的位置,这个参数必须有  
  148.         String callback = request.getParameter("CKEditorFuncNum");  
  149.         out.println("<script type=\"text/javascript\">");  
  150.         out.println("window.parent.CKEDITOR.tools.callFunction(" + callback  
  151.                 + ",'" + fileUrl + "',''" + ")");  
  152.         out.println("</script>");  
  153.         out.flush();  
  154.         out.close();  
  155.         if (debug)  
  156.             System.out.println("--- END DOPOST ---");  
  157.     }  
  158.     /** 
  159.      * 获取文件名的方法 
  160.      */  
  161.     private static String getNameWithoutExtension(String fileName) {  
  162.         return fileName.substring(0, fileName.lastIndexOf("."));  
  163.     }  
  164.     /** 
  165.      * 获取扩展名的方法 
  166.      */  
  167.     private String getExtension(String fileName) {  
  168.         return fileName.substring(fileName.lastIndexOf(".") + 1);  
  169.     }  
  170.     /** 
  171.      * 字符串像ArrayList转化的方法 
  172.      */  
  173.     private ArrayList stringToArrayList(String str) {  
  174.         if (debug)  
  175.             System.out.println(str);  
  176.         String[] strArr = str.split("\\|");  
  177.         ArrayList tmp = new ArrayList();  
  178.         if (str.length() > 0) {  
  179.             for (int i = 0; i < strArr.length; ++i) {  
  180.                 if (debug)  
  181.                     System.out.println(i + " - " + strArr[i]);  
  182.                 tmp.add(strArr[i].toLowerCase());  
  183.             }  
  184.         }  
  185.         return tmp;  
  186.     }  
  187.     /** 
  188.      * 判断扩展名是否允许的方法 
  189.      */  
  190.     private boolean extIsAllowed(String fileType, String ext) {  
  191.         ext = ext.toLowerCase();  
  192.         ArrayList allowList = (ArrayList) allowedExtensions.get(fileType);  
  193.         ArrayList denyList = (ArrayList) deniedExtensions.get(fileType);  
  194.         if (allowList.size() == 0) {  
  195.             if (denyList.contains(ext)) {  
  196.                 return false;  
  197.             } else {  
  198.                 return true;  
  199.             }  
  200.         }  
  201.         if (denyList.size() == 0) {  
  202.             if (allowList.contains(ext)) {  
  203.                 return true;  
  204.             } else {  
  205.                 return false;  
  206.             }  
  207.         }  
  208.         return false;  
  209.     }  
  210. }  

    只要在页面中的script中设置了上传属性,我们打开图片时就能看到上传选项卡了,选择图片后,点击上传到服务器,上传成功就会自动跳到图像选项卡,可以看到源文件已经存在服务器的目标目录中了,此时,我们就可以在编辑器中编辑上传的图片了,非常方便。 
 
    下面我们进行图片上传测试,可以看到如下效果。 
 
    提交后可以看到,数据获得效果,是完全一致的,这样使用CKEditor上传文件就已经成功了。 
 
    我们查看源文件,得到如下结果。 
Html代码    收藏代码
  1. <html>  
  2. <head>  
  3. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">  
  4. <title>Display Content</title>  
  5. </head>  
  6. <body>  
  7. <center>  
  8. <table width="600" border="0" bordercolor="000000"  
  9.     style="table-layout: fixed;">  
  10.     <tbody>  
  11.         <tr>  
  12.             <td width="100" bordercolor="ffffff">主题:</td>  
  13.             <td width="500" bordercolor="ffffff">图片上传测试</td>  
  14.         </tr>  
  15.         <tr>  
  16.             <td valign="top" bordercolor="ffffff">内容:</td>  
  17.             <td valign="top" bordercolor="ffffff">  
  18.             <p style="text-align: center;"><span style="color: #f00;"><strong><span  
  19.                 style="font-family: courier new, courier, monospace;"><span  
  20.                 style="font-size: 48px;">图片上传测试</span></span></strong></span></p>  
  21.             <p style="text-align: center;"><img alt=""  
  22.                 src="/ckeditor/UserFiles/Image/201002/20100217232748000.gif"  
  23.                 style="width: 133px; height: 41px;"></p>  
  24.             <p style="text-align: center;"><span  
  25.                 style="font-family: courier new, courier, monospace;"><br>  
  26.             </span></p>  
  27.             </td>  
  28.         </tr>  
  29.     </tbody>  
  30. </table>  
  31. </center>  
  32. </body>  
  33. </html>  

    在服务器目录中,上传的文件已经存在其中了。 

    欢迎交流,希望对使用者有用。附件中新增本项目的源码下载。(附件暂到此处下载 http://sarin.iteye.com/blog/599499


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值