1. 在web中配置应用Fck;
2. 用Fck自带Api做非空验证;
3. 修改文件上传的保存路径;
4. 对文件上传做大小控制;
一. 配置和应用
去官网上下载fckeditor-java-demo-2.6.rar,里面有我们需要的所有js和用于文件上传的java包。
(1)新建一工程,在webroot下建一文件夹起名为js,把fckeditor-java-demo-2.6.rar解压,把得到的fckeditor文件夹给扔到这个文件夹下面,并且可以把其中所有以“_”开头的文件夹给删掉。
(2)把需要的第三方包从fckeditor-java-demo中复制到新建的工程中,这里要注意的是若工程是以前遗留下来的,那么有的包可能会有重复,记得留下最新版本的包,否则有可能在使用时会出现异常,比如我之前有遇到过,工程里有commons-fileupload-1.1.jar和commons-io-1.2.jar都比fckeditor下使用的包要旧,于是在浏览文件服务器时就报了java.lang.NoSuchFieldError: DIRECTORY的错误,只要删掉旧包就可以了。
(3)在web.xml中,加入如下配置
- <servlet>
- <servlet-name>ConnectorServlet</servlet-name>
- <servlet-class>
- net.fckeditor.connector.ConnectorServlet
- </servlet-class>
- <load-on-startup>1</load-on-startup>
- </servlet>
- <servlet-mapping>
- <servlet-name>ConnectorServlet</servlet-name>
- <url-pattern>/js/fckeditor/editor/filemanager/connectors/*</url-pattern>
- </servlet-mapping>
这里要注意的是url-pattern参数,由于我们是把fckeditor放在了js文件夹下,所以在这个参数中就要加上/js。
(4)在src下新建一个fckeditor.properties文件,文件中的做如下配置
- connector.userActionImpl=net.fckeditor.requestcycle.impl.EnabledUserAction
这个文件用可以覆盖fck中的一些默认配置,稍后我们还会讲到其他的配置,这里我们先看connector.userActionImpl,它有三个值:
UserActionImpl已过期,一般不用;
EnabledUserAction允许文件上传浏览操作;
DisabledUserAction不允许文件上传浏览操作;
它们都继承于一个UserAction接口,并且实现也非常简单,都只有一行代码,返回true或false。
(5)在页面中我们使用fck标签来显示fckeditor编辑器
- <%@ taglib uri="http://java.fckeditor.net" prefix="FCK" %>
- <FCK:editor instanceName="EditorDefault" inputName="content" basePath="/js/fckeditor" />
FCK标签有几个参数,这里说明下:
height,width代表高和宽;
value可以赋初始值;
basePath是fckeditor的相对路径,若是直接放在webroot下可以不用填;
toolbarSet编辑器使用的工具集名称,可以可以去fckconfig.js文件定义一个新的FCKConfig.ToolbarSets,然后在页面中使用;
inputName是服务端取值时使用的参数名;
instanceName代表编辑器的唯一名称(相当于ID);
二. Fck自带API
fck还有些有用的api,比如要在提交表单的时候验证内容非空,用一般的document.getElementById("").value==null来判断是不行的,应该用
- var content = FCKeditorAPI.GetInstance("EditorDefault");
- if(content.GetXHTML() == ''){
- alert("广告内容不能为空!");
- content.Focus();
- return false;
- }
EditorDefault是刚才Fck标签里的instanceName参数的值,还要注意Focus()函数也是fck自带的函数,一般的focus()不能用在这里。
三. 文件上传保存路径修改
按以上配置就可以把fck很好的给跑起来了,包括图片Flash文件的上传浏览等操作。上传的文件将默认的保持在工程fckeditor文件夹的userfiles子文件夹下,有的人可能不喜欢这个路径,甚至不喜欢把上传文件的目录放在工程下,那我们就可以使用绝对路径,也很简单,按如下配置:
(1)在fckeditor.properties文件中,添加
- connector.userFilesAbsolutePath = E:/image
- connector.userFilesPath = http://localhost:8080/image
- connector.userPathBuilderImpl = net.fckeditor.requestcycle.impl.ServerRootPathBuilder
- connector.impl = net.fckeditor.connector.impl.LocalConnector
第一个参数很好理解,是保存上传文件的绝对路径,第二个参数是在web上使用文件时的虚拟目录。后两个参数是指定接口的实现类。以上的两个实现类将会直接读取属性文件中的值后返回,若是不配置这两个属性的话,默认的实现类会把以上两个路径当做相对路径来使用,在返回之前会加上上下文路径。
(2)配置tomcat,修改server.xml,添加一个虚拟目录
- <Context path="/image" docBase="E:\image" reloadable="true" debug="0"/>
这个context应该包在host标签之中。
OK,很简单的两个步骤,现在上传文件则保存在你所需要的位置了。之前被网上误导了,为了实现使用绝对路径居然还去改源代码,后来在改的过程中发现fck已经都为你想到了,真的很人性化。
四. 文件上传大小控制
最后我们在做文件上传的时候都需要限制文件大小,这个就需要改下源代码了。下载fckeditor-java-2.6-src.zip,解压,但是我们只需要动几个文件,步骤如下:
(1)在fckeditor.properties文件中,添加两个属性值,用来设置上传的图片或Flash所允许的最大值,单位是比特。
- image.allowedMaxSize = 307200
- flash.allowedMaxSize = 3072000
(2)修改net.fckeditor.handlers.PropertiesLoader,这个类用于从属性文件中读取指定的属性值,我们添加两个方法,用于从属性文件中读取我们刚设置的那两个值:
- public static int getImageAllowedImageSize(){
- int allowedMaxSize = 0;
- String tempStr = properties.getProperty("image.allowedMaxSize");
- if(tempStr != null){
- try {
- allowedMaxSize = Integer.parseInt(tempStr);
- } catch (NumberFormatException e) {
- logger.error("从配置文件读取的允许图片上传的最大值从字符串型转化为数值型出错!", e);
- }
- }
- return allowedMaxSize;
- }
- public static int getFlashAllowedImageSize(){
- int allowedMaxSize = 0;
- String tempStr = properties.getProperty("flash.allowedMaxSize");
- if(tempStr != null){
- try{
- allowedMaxSize = Integer.parseInt(tempStr);
- } catch (NumberFormatException e) {
- logger.error("从配置文件读取的允许Flash上传的最大值从字符串型转化为数值型出错!", e);
- }
- }
- return allowedMaxSize;
- }
(3)修改net.fckeditor.handlers.ResourceType,这个类用于定义上传文件的种类,我们添加一个私有变量,表示允许上传的最大值,再添加一个构造方法,在这个构造方法中初始图片类型和Flash类型的上传大小,所以图片和Flash类型的静态变量将调用这个初始化方法。
- //控制上传大小(单位b)
- private int allowedMaxSize = 0;
- /** Resource type <code>Flash</code> */
- public static final ResourceType FLASH = new ResourceType("Flash",
- PropertiesLoader.getFlashResourceTypePath(), Utils
- .getSet(PropertiesLoader
- .getFlashResourceTypeAllowedExtensions()), Utils
- .getSet(PropertiesLoader
- .getFlashResourceTypeDeniedExtensions()),
- PropertiesLoader.getFlashAllowedImageSize());
- /** Resource type <code>Image</code> */
- public static final ResourceType IMAGE = new ResourceType("Image",
- PropertiesLoader.getImageResourceTypePath(), Utils
- .getSet(PropertiesLoader
- .getImageResourceTypeAllowedExtensions()), Utils
- .getSet(PropertiesLoader
- .getImageResourceTypeDeniedExtensions()),
- PropertiesLoader.getImageAllowedImageSize());
- /**
- * This constructor has been made intentionally made private to provide
- * pre-defined types only.
- *
- * @param name
- * the name of the new resource type
- * @param path
- * the absolute path of the new resource type
- * @param allowedEextensions
- * the allowed extensions set of the new resource type
- * @param deniedExtensions
- * the denied extensions set of the new resource type
- * @param allowedMaxSize
- * 允许上传的最大值
- * @throws IllegalArgumentException
- * if both sets are empty
- * @throws IllegalArgumentException
- * if both sets contain extensions
- */
- private ResourceType(final String name, final String path,
- final Set<String> allowedEextensions,
- final Set<String> deniedExtensions,
- int allowedMaxSize) {
- this(name, path, allowedEextensions, deniedExtensions);
- this.allowedMaxSize = allowedMaxSize;
- }
(4)修改net.fckeditor.connector.Dispatcher,这个类用于处理相关的文件操作,修改UploadResponse doPost(final HttpServletRequest request)方法,在上传文件之前做下大小判断
- UploadResponse doPost(final HttpServletRequest request) {
- ...
- else if (type.equals(ResourceType.IMAGE)
- && PropertiesLoader.isSecureImageUploads()
- && !UtilsFile.isImage(uplFile.getInputStream())) {
- uploadResponse = UploadResponse.getInvalidFileTypeError();
- }
- //判断文件上传大小是否合法,非法的话就返回一个自定义的表示文件太大的状态值
- else if (type.getAllowedMaxSize() > 0 && uplFile.getSize() > type.getAllowedMaxSize()) {
- uploadResponse = new UploadResponse(204);
- } else {
- String sanitizedFileName = UtilsFile
- .sanitizeFileName(fileName);
- logger.debug("Parameter NewFile (sanitized): {}",
- sanitizedFileName);
- ...
- }
(4)修改fckeditor\editor\dialog\fck_image\fck_image.js,在function OnUploadCompleted( errorNumber, fileUrl, fileName, customMsg )方法下新增一个对我们刚定义的204状态码的处理:
- switch ( errorNumber )
- {
- case 0 : // No errors
- alert( 'Your file has been successfully uploaded' ) ;
- break ;
- case 1 : // Custom error
- alert( customMsg ) ;
- return ;
- case 101 : // Custom warning
- alert( customMsg ) ;
- break ;
- case 201 :
- alert( 'A file with the same name is already available. The uploaded file has been renamed to "' + fileName + '"' ) ;
- break ;
- case 202 :
- alert( 'Invalid file type' ) ;
- return ;
- case 203 :
- alert( "Security error. You probably don't have enough permissions to upload. Please check your server." ) ;
- return ;
- case 204 :
- alert( "文件太大." ) ;
- return ;
- case 500 :
- alert( 'The connector is disabled' ) ;
- break ;
- default :
- alert( 'Error on file upload. Error number: ' + errorNumber ) ;
- return ;
- }
至此,文件上传大小控制就修改好了,文件大小的最大值可以直接在属性文件中配置。其实fck for java服务端的源码还是比较简单的,有什么特殊的需求查看修改下源码也不会难道哪里去。
关于异常:java.lang.ClassNotFoundException: net.fckeditor.requestcycle.impl.UserActionImpl ,如果配置和jar包都没有问题的话检查一下fckeditor.properties中的空格。
Security error. You probably don't have enough permissions to upload. Please check your server.
You are not authorized to browse/list files and/or folders!原因:struts2对request进行了封装,所以当fck的request.getinputStream的时候就会出错.修改的方法就是对filtermapping的路径进行修改。
web.xml(原)
- <filter-mapping>
- <filter-name>struts2</filter-name>
- <url-pattern>/*</url-pattern>
- </filter-mapping>
<filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
改为:“*.action”。
另外,jsp页面上面用到了struts2的tag,那么就要增加一个*.jsp的url-pattern。
修改后如下:
- <filter-mapping>
- <filter-name>struts2</filter-name>
- <url-pattern>*.action</url-pattern>
- </filter-mapping>
- <filter-mapping>
- <filter-name>struts2</filter-name>
- <url-pattern>*.jsp</url-pattern>
- </filter-mapping>
<filter-mapping> <filter-name>struts2</filter-name> <url-pattern>*.action</url-pattern> </filter-mapping> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>*.jsp</url-pattern> </filter-mapping>
如果你用到struts2的datetimepicker标签发现他不能用了
你查看源代码的时候会发现有如下代码:
- <link rel="stylesheet" href="/para/struts/xhtml/styles.css" type="text/css"/>
- <script language="JavaScript" type="text/javascript">
- // Dojo configuration
- djConfig = {
- baseRelativePath: "/para/struts/dojo",
- isDebug: false,
- bindEncoding: "utf-8",
- debugAtAllCosts: true // not needed, but allows the Venkman debugger to work with the includes
- };
- </script>
- <script language="JavaScript" type="text/javascript"
- src="/para/struts/dojo/dojo.js"></script>
- <script language="JavaScript" type="text/javascript"
- src="/para/struts/simple/dojoRequire.js"></script>
<link rel="stylesheet" href="/para/struts/xhtml/styles.css" type="text/css"/>
<script language="JavaScript" type="text/javascript">
// Dojo configuration
djConfig = {
baseRelativePath: "/para/struts/dojo",
isDebug: false,
bindEncoding: "utf-8",
debugAtAllCosts: true // not needed, but allows the Venkman debugger to work with the includes
};
</script>
<script language="JavaScript" type="text/javascript"
src="/para/struts/dojo/dojo.js"></script>
<script language="JavaScript" type="text/javascript"
src="/para/struts/simple/dojoRequire.js"></script>
这时加上以下过滤后问题解决:
- <filter-mapping>
- <filter-name>struts2</filter-name>
- <url-pattern>/struts/*</url-pattern>
- </filter-mapping>
<filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/struts/*</url-pattern> </filter-mapping>
当然要用datetimepicker标签在<head>中还要加入 <s:head theme="ajax"/>