以前公司购买过eWebEditor,功能应该还是不错的,但即便到了现在,也还仅是一个IE only的版本,无法满足现在差异化的需求。故前段时间下了最新的FCKeditor2.3.3版本下来(当然了,连带java的integration),demo来看看,发现有几个地方非常不爽:
1、上载的文件,只能放在URL可及的地方(如默认只能放到嵌入应用路径的/UserFiles/下);
2、没有明确的上载视频的按钮;
3、图片、FLASH、附件上载等,步骤多,复杂度高(想想,用户不都是高手)。
怎么办呢,改!
一、第一个就是增加一个FileLocatorServlet,思路很简单:通过这个服务来定位文件,而不是之间产生链接,既是安全的考虑,也是应用集群的一个重要考虑点。而且原来的几个servlet的配置罗嗦且重叠,难以让人产生美感。所谓代码胜千言,通过下面的web.xml大家应该可以看出修理的要点:
		
				  1
				 <?
				xml version="1.0" encoding="ISO-8859-1"
				?>
				<?
				xml version="1.0" encoding="ISO-8859-1"
				?>
				
						
				
				  2
				
						 
						
				
				  3
				
						 <!
				DOCTYPE web-app
				
				<!
				DOCTYPE web-app
				  4
				
						 PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"
  PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"
				  5
				
						 "http://java.sun.com/j2ee/dtds/web-app_2_2.dtd"
				>
  "http://java.sun.com/j2ee/dtds/web-app_2_2.dtd"
				>
				
						
				
				  6
				
						 
						
				
				  7
				
						 <
				web-app
				>
				
				<
				web-app
				>
				
						
				
				  8
				
						 <
				display-name
				>
				FCKeditor Test Application
				</
				display-name
				>
  
				<
				display-name
				>
				FCKeditor Test Application
				</
				display-name
				>
				  
				  9
				
						 <
				context-param
				>
    
				<
				context-param
				>
				
						
				
				 10
				
						 <!--
				 setting the FCKecitor context based parameters 
				-->
        
				<!--
				 setting the FCKecitor context based parameters 
				-->
				
						
				
				 11
				
						 <!--
				 baseDir means the root of the uploaded file/image/flash stored
        
				<!--
				 baseDir means the root of the uploaded file/image/flash stored 
				 12
				
						 the prefix of 'file:/' means strore in a file system root that cannot get from webapp url
             the prefix of 'file:/' means strore in a file system root that cannot get from webapp url
				 13
				
						 -->
        
				-->
				
						
				
				 14
				
						 <
				param-name
				>
				baseDir
				</
				param-name
				>
        
				<
				param-name
				>
				baseDir
				</
				param-name
				>
				
						
				
				 15
				
						 <
				param-value
				>
				file:/C:/Temp/FCKeditorUpload/
				</
				param-value
				>
        
				<
				param-value
				>
				file:/C:/Temp/FCKeditorUpload/
				</
				param-value
				>
				
						
				
				 16
				
						 </
				context-param
				>
    
				</
				context-param
				>
				 
				 17
				
						 
						
				
				 18
				
						 <
				context-param
				>
    
				<
				context-param
				>
				
						
				
				 19
				
						 <!--
        
				<!--
				 
				 20
				
						 if the baseDir prefix by 'file:/',please set it.
             if the baseDir prefix by 'file:/',please set it.
				 21
				
						 -->
        
				-->
				
						
				
				 22
				
						 <
				param-name
				>
				fileLocator
				</
				param-name
				>
        
				<
				param-name
				>
				fileLocator
				</
				param-name
				>
				
						
				
				 23
				
						 <
				param-value
				>
				/editor/filemanager/browser/default/service/jsp/filelocator
				</
				param-value
				>
        
				<
				param-value
				>
				/editor/filemanager/browser/default/service/jsp/filelocator
				</
				param-value
				>
				
						
				
				 24
				
						 </
				context-param
				>
    
				</
				context-param
				>
				 
				 25
				
						 
						
				
				 26
				
						 <
				context-param
				>
    
				<
				context-param
				>
				
						
				
				 27
				
						 <!--
        
				<!--
				 
				 28
				
						 debug setting,true means verbose output to the console.
             debug setting,true means verbose output to the console.
				 29
				
						 -->
        
				-->
				
						
				
				 30
				
						 <
				param-name
				>
				debug
				</
				param-name
				>
        
				<
				param-name
				>
				debug
				</
				param-name
				>
				
						
				
				 31
				
						 <
				param-value
				>
				true
				</
				param-value
				>
        
				<
				param-value
				>
				true
				</
				param-value
				>
				
						
				
				 32
				
						 </
				context-param
				>
    
				</
				context-param
				>
				 
				 33
				
						 
						
				
				 34
				
						 <
				context-param
				>
    
				<
				context-param
				>
				
						
				
				 35
				
						 <!--
        
				<!--
				 
				 36
				
						 enabled setting,true means upload enabled.
             enabled setting,true means upload enabled.
				 37
				
						 -->
        
				-->
				
						
				
				 38
				
						 <
				param-name
				>
				enabled
				</
				param-name
				>
        
				<
				param-name
				>
				enabled
				</
				param-name
				>
				
						
				
				 39
				
						 <
				param-value
				>
				true
				</
				param-value
				>
        
				<
				param-value
				>
				true
				</
				param-value
				>
				
						
				
				 40
				
						 </
				context-param
				>
    
				</
				context-param
				>
				 
				 41
				
						 
						
				
				 42
				
						 <
				context-param
				>
    
				<
				context-param
				>
				
						
				
				 43
				
						 <!--
        
				<!--
				 
				 44
				
						 encoding,the response encoding of the file/image/flash,default is UTF-8
             encoding,the response encoding of the file/image/flash,default is UTF-8
				 45
				
						 -->
        
				-->
				
						
				
				 46
				
						 <
				param-name
				>
				encoding
				</
				param-name
				>
        
				<
				param-name
				>
				encoding
				</
				param-name
				>
				
						
				
				 47
				
						 <
				param-value
				>
				UTF-8
				</
				param-value
				>
        
				<
				param-value
				>
				UTF-8
				</
				param-value
				>
				
						
				
				 48
				
						 </
				context-param
				>
    
				</
				context-param
				>
				 
				 49
				
						 
						
				
				 50
				
						 <
				context-param
				>
    
				<
				context-param
				>
				
						
				
				 51
				
						 <!--
        
				<!--
				 
				 52
				
						 contentTypeMapping,a map for the response ContentType
             contentTypeMapping,a map for the response ContentType
				 53
				
						 -->
        
				-->
				
						
				
				 54
				
						 <
				param-name
				>
				contentTypeMapping
				</
				param-name
				>
        
				<
				param-name
				>
				contentTypeMapping
				</
				param-name
				>
				
						
				
				 55
				
						 <
				param-value
				>
				doc=application/vnd.ms-word
        
				<
				param-value
				>
				doc=application/vnd.ms-word
				 56
				
						 |xls=application/vnd.ms-excel
        |xls=application/vnd.ms-excel
				 57
				
						 |jpg=image/jpeg
        |jpg=image/jpeg
				 58
				
						 |gif=image/gif
        |gif=image/gif
				 59
				
						 |swf=application/x-shockwave-flash
        |swf=application/x-shockwave-flash
				 60
				
						 |avi=video/x-msvideo
        |avi=video/x-msvideo
				 61
				
						 </
				param-value
				>
        
				</
				param-value
				>
				
						
				
				 62
				
						 </
				context-param
				>
    
				</
				context-param
				>
				 
				 63
				
						 
						
				
				 64
				
						 <
				context-param
				>
    
				<
				context-param
				>
				
						
				
				 65
				
						 <!--
        
				<!--
				 
				 66
				
						 allowedExtensionsFile,the logic is 'Not allowed means deny.'
             allowedExtensionsFile,the logic is 'Not allowed means deny.'
				 67
				
						 -->
        
				-->
				
						
				
				 68
				
						 <
				param-name
				>
				allowedExtensionsFile
				</
				param-name
				>
        
				<
				param-name
				>
				allowedExtensionsFile
				</
				param-name
				>
				
						
				
				 69
				
						 <
				param-value
				>
				doc|xls|pdf|avi
				</
				param-value
				>
        
				<
				param-value
				>
				doc|xls|pdf|avi
				</
				param-value
				>
				
						
				
				 70
				
						 </
				context-param
				>
    
				</
				context-param
				>
				 
				 71
				
						 
						
				
				 72
				
						 <
				context-param
				>
    
				<
				context-param
				>
				
						
				
				 73
				
						 <!--
        
				<!--
				 
				 74
				
						 allowedExtensionsImage,the logic is 'Not allowed means deny.'
             allowedExtensionsImage,the logic is 'Not allowed means deny.'
				 75
				
						 -->
        
				-->
				
						
				
				 76
				
						 <
				param-name
				>
				allowedExtensionsImage
				</
				param-name
				>
        
				<
				param-name
				>
				allowedExtensionsImage
				</
				param-name
				>
				
						
				
				 77
				
						 <
				param-value
				>
				jpg|gif|png
				</
				param-value
				>
        
				<
				param-value
				>
				jpg|gif|png
				</
				param-value
				>
				
						
				
				 78
				
						 </
				context-param
				>
    
				</
				context-param
				>
				 
				 79
				
						 
						
				
				 80
				
						 <
				context-param
				>
    
				<
				context-param
				>
				
						
				
				 81
				
						 <!--
        
				<!--
				 
				 82
				
						 allowedExtensionsFlash,the logic is 'Not allowed means deny.'
             allowedExtensionsFlash,the logic is 'Not allowed means deny.'
				 83
				
						 -->
        
				-->
				
						
				
				 84
				
						 <
				param-name
				>
				allowedExtensionsFlash
				</
				param-name
				>
        
				<
				param-name
				>
				allowedExtensionsFlash
				</
				param-name
				>
				
						
				
				 85
				
						 <
				param-value
				>
				swf|fla
				</
				param-value
				>
        
				<
				param-value
				>
				swf|fla
				</
				param-value
				>
				
						
				
				 86
				
						 </
				context-param
				>
    
				</
				context-param
				>
				
						
				
				 87
				
						 
						
				
				 88
				
						 <
				servlet
				>
    
				<
				servlet
				>
				
						
				
				 89
				
						 <
				servlet-name
				>
				Connector
				</
				servlet-name
				>
        
				<
				servlet-name
				>
				Connector
				</
				servlet-name
				>
				
						
				
				 90
				
						 <
				servlet-class
				>
				com.fredck.FCKeditor.connector.ConnectorServlet
				</
				servlet-class
				>
        
				<
				servlet-class
				>
				com.fredck.FCKeditor.connector.ConnectorServlet
				</
				servlet-class
				>
				
						
				
				 91
				
						 <
				load-on-startup
				>
				1
				</
				load-on-startup
				>
        
				<
				load-on-startup
				>
				1
				</
				load-on-startup
				>
				
						
				
				 92
				
						 </
				servlet
				>
    
				</
				servlet
				>
				
						
				
				 93
				
						 
    
				 94
				
						 <
				servlet
				>
    
				<
				servlet
				>
				
						
				
				 95
				
						 <
				servlet-name
				>
				FileLocator
				</
				servlet-name
				>
        
				<
				servlet-name
				>
				FileLocator
				</
				servlet-name
				>
				
						
				
				 96
				
						 <
				servlet-class
				>
				com.fredck.FCKeditor.service.FileLocatorServlet
				</
				servlet-class
				>
        
				<
				servlet-class
				>
				com.fredck.FCKeditor.service.FileLocatorServlet
				</
				servlet-class
				>
				
						
				
				 97
				
						 <
				load-on-startup
				>
				1
				</
				load-on-startup
				>
        
				<
				load-on-startup
				>
				1
				</
				load-on-startup
				>
				
						
				
				 98
				
						 </
				servlet
				>
    
				</
				servlet
				>
				
						
				
				 99
				
						 
						
				
				100
				
						 <
				servlet
				>
    
				<
				servlet
				>
				
						
				
				101
				
						 <
				servlet-name
				>
				SimpleUploader
				</
				servlet-name
				>
        
				<
				servlet-name
				>
				SimpleUploader
				</
				servlet-name
				>
				
						
				
				102
				
						 <
				servlet-class
				>
				com.fredck.FCKeditor.uploader.SimpleUploaderServlet
				</
				servlet-class
				>
        
				<
				servlet-class
				>
				com.fredck.FCKeditor.uploader.SimpleUploaderServlet
				</
				servlet-class
				>
				
						
				
				103
				
						 <
				load-on-startup
				>
				1
				</
				load-on-startup
				>
        
				<
				load-on-startup
				>
				1
				</
				load-on-startup
				>
				
						
				
				104
				
						 </
				servlet
				>
    
				</
				servlet
				>
				
						
				
				105
				
						 
						
				
				106
				
						 <
				servlet-mapping
				>
  
				<
				servlet-mapping
				>
				
						
				
				107
				
						 <
				servlet-name
				>
				Connector
				</
				servlet-name
				>
    
				<
				servlet-name
				>
				Connector
				</
				servlet-name
				>
				
						
				
				108
				
						 <
				url-pattern
				>
				/editor/filemanager/browser/default/connectors/jsp/connector
				</
				url-pattern
				>
    
				<
				url-pattern
				>
				/editor/filemanager/browser/default/connectors/jsp/connector
				</
				url-pattern
				>
				
						
				
				109
				
						 </
				servlet-mapping
				>
  
				</
				servlet-mapping
				>
				
						
				
				110
				
						 
  
				111
				
						 <
				servlet-mapping
				>
  
				<
				servlet-mapping
				>
				
						
				
				112
				
						 <
				servlet-name
				>
				SimpleUploader
				</
				servlet-name
				>
    
				<
				servlet-name
				>
				SimpleUploader
				</
				servlet-name
				>
				
						
				
				113
				
						 <
				url-pattern
				>
				/editor/filemanager/upload/simpleuploader
				</
				url-pattern
				>
    
				<
				url-pattern
				>
				/editor/filemanager/upload/simpleuploader
				</
				url-pattern
				>
				
						
				
				114
				
						 </
				servlet-mapping
				>
  
				</
				servlet-mapping
				>
				  
				115
				
						 
  
				116
				
						 <
				servlet-mapping
				>
  
				<
				servlet-mapping
				>
				
						
				
				117
				
						 <
				servlet-name
				>
				FileLocator
				</
				servlet-name
				>
    
				<
				servlet-name
				>
				FileLocator
				</
				servlet-name
				>
				
						
				
				118
				
						 <
				url-pattern
				>
				/editor/filemanager/browser/default/service/jsp/filelocator
				</
				url-pattern
				>
    
				<
				url-pattern
				>
				/editor/filemanager/browser/default/service/jsp/filelocator
				</
				url-pattern
				>
				
						
				
				119
				
						 </
				servlet-mapping
				>
  
				</
				servlet-mapping
				>
				  
				120
				
						 
						
				
				121
				
						 </
				web-app
				>
				
				</
				web-app
				>
		 
		连带FCKeditorConfigurations.java一并修理,配置统一且singleton。关键代码为:
		
				 1
				 
				
						
				
				 2
				
						 
						 /** */
				
						/**
    
				/** */
				
						/**
						
								
						
						 3
						
								 * Make the configuration sigleton
     * Make the configuration sigleton
						 4
						
								 * 
						@param
						 sc
     * 
						@param
						 sc
						 5
						
								 * 
						@return
						 the static configuration map
     * 
						@return
						 the static configuration map
						 6
						
								 */
     
						*/
				
				
						
				
				 7
				
						 
						 public
				 
				static
				 Map getContextConfigurationsInstance(ServletContext sc)
    
				public
				 
				static
				 Map getContextConfigurationsInstance(ServletContext sc)
				
						 {
				
				
						{
						 8
						
								 
								 if
						(contextConfigurations
						==
						null
						)
        
						if
						(contextConfigurations
						==
						null
						)
						
								 {
						
						
								{
								 9
								
										 initContextConfigurations(sc);
            initContextConfigurations(sc);
								10
								
										 }
        }
						
						
								
						
						11
						
								 return
						 contextConfigurations;
        
						return
						 contextConfigurations;
						12
						
								 }
    }
				
				
						
				
				13
				
						 
    
				14
				
						 
						 /** */
				
						/**
    
				/** */
				
						/**
						
								
						
						15
						
								 * Init all the FCKeditor configuration.
     * Init all the FCKeditor configuration.
						16
						
								 * add by zhengxq
     * add by zhengxq
						17
						
								 * 
						@param
						 sc
     * 
						@param
						 sc
						18
						
								 */
     
						*/
				
				
						
				
				19
				
						 
						 private
				 
				static
				 
				void
				 initContextConfigurations(ServletContext sc)
    
				private
				 
				static
				 
				void
				 initContextConfigurations(ServletContext sc)
				
						 {
				
				
						{
						20
						
								 if
						 (debug)
        
						if
						 (debug)
						21
						
								 System.out.println(
						"
						\r\n---- FCKeditorConfigurations for java initialization started ----
						"
						);
            System.out.println(
						"
						\r\n---- FCKeditorConfigurations for java initialization started ----
						"
						);
						22
						
								 
        
						23
						
								 String baseDir 
						=
						 sc.getInitParameter(
						"
						baseDir
						"
						);
        String baseDir 
						=
						 sc.getInitParameter(
						"
						baseDir
						"
						);
						24
						
								 String fileLocator 
						=
						 sc.getInitParameter(
						"
						fileLocator
						"
						);
        String fileLocator 
						=
						 sc.getInitParameter(
						"
						fileLocator
						"
						);
						25
						
								 String debugStr 
						=
						 sc.getInitParameter(
						"
						debug
						"
						);
        String debugStr 
						=
						 sc.getInitParameter(
						"
						debug
						"
						);
						26
						
								 String enabledStr 
						=
						 sc.getInitParameter(
						"
						enabled
						"
						);
        String enabledStr 
						=
						 sc.getInitParameter(
						"
						enabled
						"
						);        
						27
						
								 String encoding 
						=
						 sc.getInitParameter(
						"
						encoding
						"
						);
        String encoding 
						=
						 sc.getInitParameter(
						"
						encoding
						"
						);
						28
						
								 String contentTypeMapping 
						=
						 sc.getInitParameter(
						"
						contentTypeMapping
						"
						);
        String contentTypeMapping 
						=
						 sc.getInitParameter(
						"
						contentTypeMapping
						"
						);
						29
						
								 String AllowedExtensionsFile 
						=
						 sc.getInitParameter(
						"
						allowedExtensionsFile
						"
						);
        String AllowedExtensionsFile 
						=
						 sc.getInitParameter(
						"
						allowedExtensionsFile
						"
						);
						30
						
								 String AllowedExtensionsImage 
						=
						 sc.getInitParameter(
						"
						allowedExtensionsImage
						"
						);
        String AllowedExtensionsImage 
						=
						 sc.getInitParameter(
						"
						allowedExtensionsImage
						"
						);
						31
						
								 String AllowedExtensionsFlash 
						=
						 sc.getInitParameter(
						"
						allowedExtensionsFlash
						"
						);
        String AllowedExtensionsFlash 
						=
						 sc.getInitParameter(
						"
						allowedExtensionsFlash
						"
						);
						32
						
								 
        
						33
						
								 debug 
						=
						 (
						new
						 Boolean(debugStr)).booleanValue();
        debug 
						=
						 (
						new
						 Boolean(debugStr)).booleanValue();
						34
						
								 encoding 
						=
						 (encoding
						==
						null
						 
						||
						 encoding.length()
						==
						0
						)
						?
						"
						UTF-8
						"
						:encoding;
        encoding 
						=
						 (encoding
						==
						null
						 
						||
						 encoding.length()
						==
						0
						)
						?
						"
						UTF-8
						"
						:encoding;
						35
						
								 
        
						36
						
								 if
						(baseDir
						==
						null
						 
						||
						 baseDir.length()
						==
						0
						) baseDir 
						=
						 defaultBaseDir;
        
						if
						(baseDir
						==
						null
						 
						||
						 baseDir.length()
						==
						0
						) baseDir 
						=
						 defaultBaseDir;
						37
						
								 String realBaseDir 
						=
						 defaultBaseDir;
        String realBaseDir 
						=
						 defaultBaseDir;
						38
						
								 
								 if
						 (baseDir.startsWith(fileSystemUriPrefix))
        
						if
						 (baseDir.startsWith(fileSystemUriPrefix)) 
						
								 {
						
						
								{
								39
								
										 realBaseDir 
								=
								 baseDir.substring(fileSystemUriPrefix.length());
            realBaseDir 
								=
								 baseDir.substring(fileSystemUriPrefix.length());            
								40
								
										 
										 }
						
						 
						else
        }
						
						 
						else
						 
						
								 {
						
						
								{
								41
								
										 realBaseDir 
								=
								 sc.getRealPath(baseDir);
            realBaseDir 
								=
								 sc.getRealPath(baseDir);
								42
								
										 fileLocator 
								=
								 
								null
								;
								//
								no use and should set null
            fileLocator 
								=
								 
								null
								;
								//
								no use and should set null
								
										
								
								43
								
										 }
								
								        }
						
						
								
						
						44
						
								 File baseFile
						=
						new
						 File(realBaseDir);
        File baseFile
						=
						new
						 File(realBaseDir);
						45
						
								 
								 if
						(
						!
						baseFile.exists())
        
						if
						(
						!
						baseFile.exists())
						
								 {
						
						
								{
								46
								
										 baseFile.mkdir();
            baseFile.mkdir();
								47
								
										 }
        }
						
						
								
						
						48
						
								 contextConfigurations 
						=
						 
						new
						 HashMap();
        contextConfigurations 
						=
						 
						new
						 HashMap();
						49
						
								 contextConfigurations.put(
						"
						baseDir
						"
						,baseDir);
        contextConfigurations.put(
						"
						baseDir
						"
						,baseDir);
						50
						
								 contextConfigurations.put(
						"
						realBaseDir
						"
						,realBaseDir);
        contextConfigurations.put(
						"
						realBaseDir
						"
						,realBaseDir);
						51
						
								 contextConfigurations.put(
						"
						fileLocator
						"
						,fileLocator);
        contextConfigurations.put(
						"
						fileLocator
						"
						,fileLocator);
						52
						
								 contextConfigurations.put(
						"
						debug
						"
						,debugStr);
        contextConfigurations.put(
						"
						debug
						"
						,debugStr);
						53
						
								 contextConfigurations.put(
						"
						enabled
						"
						,enabledStr);
        contextConfigurations.put(
						"
						enabled
						"
						,enabledStr);
						54
						
								 contextConfigurations.put(
						"
						encoding
						"
						,encoding);
        contextConfigurations.put(
						"
						encoding
						"
						,encoding);
						55
						
								 contextConfigurations.put(
						"
						contentTypeMapping
						"
						,contentTypeMappingToMap(contentTypeMapping));
        contextConfigurations.put(
						"
						contentTypeMapping
						"
						,contentTypeMappingToMap(contentTypeMapping));
						56
						
								 contextConfigurations.put(
						"
						allowedExtensionsFile
						"
						,stringToArrayList(AllowedExtensionsFile));
        contextConfigurations.put(
						"
						allowedExtensionsFile
						"
						,stringToArrayList(AllowedExtensionsFile));
						57
						
								 contextConfigurations.put(
						"
						allowedExtensionsImage
						"
						,stringToArrayList(AllowedExtensionsImage));
        contextConfigurations.put(
						"
						allowedExtensionsImage
						"
						,stringToArrayList(AllowedExtensionsImage));
						58
						
								 contextConfigurations.put(
						"
						allowedExtensionsFlash
						"
						,stringToArrayList(AllowedExtensionsFlash));
        contextConfigurations.put(
						"
						allowedExtensionsFlash
						"
						,stringToArrayList(AllowedExtensionsFlash));
						59
						
								 
        
						60
						
								 if
						 (debug)
        
						if
						 (debug)
						61
						
								 System.out.println(
						"
						\r\n---- FCKeditorConfigurations for java initialization end ----
						"
						);
            System.out.println(
						"
						\r\n---- FCKeditorConfigurations for java initialization end ----
						"
						);
						62
						
								 
        
						63
						
								 }
    }
				
		 
		
				
FileLocatorServlet.java也很简单,无非就是文件的物理定位和文件流的输出:
		
				 1
				 String type 
				=
				 request.getParameter(
				"
				Type
				"
				);
				String type 
				=
				 request.getParameter(
				"
				Type
				"
				);
				 2
				
						 String fileName 
				=
				 request.getParameter(
				"
				FileName
				"
				);
        String fileName 
				=
				 request.getParameter(
				"
				FileName
				"
				);
				 3
				
						 
						
				
				 4
				
						 String realFilePath 
				=
				 config.get(
				"
				realBaseDir
				"
				) 
				+
				 type 
				+
				 
				"
				/
				"
				 
				+
				 fileName;
        String realFilePath 
				=
				 config.get(
				"
				realBaseDir
				"
				) 
				+
				 type 
				+
				 
				"
				/
				"
				 
				+
				 fileName;
				 5
				
						 File file 
				=
				 
				new
				 File(realFilePath);
        File file 
				=
				 
				new
				 File(realFilePath);
				 6
				
						 
						 if
				 (file.exists())
        
				if
				 (file.exists()) 
				
						 {
				
				
						{
						 7
						
								 response.setHeader(
						"
						Content-Transfer-Encoding
						"
						, 
						"
						base64
						"
						);
            response.setHeader(
						"
						Content-Transfer-Encoding
						"
						, 
						"
						base64
						"
						);
						 8
						
								 response.setHeader(
						"
						Cache-Control
						"
						, 
						"
						no-store
						"
						);
            response.setHeader(
						"
						Cache-Control
						"
						, 
						"
						no-store
						"
						);
						 9
						
								 response.setHeader(
						"
						Pragma
						"
						, 
						"
						no-cache
						"
						);
            response.setHeader(
						"
						Pragma
						"
						, 
						"
						no-cache
						"
						);
						10
						
								 response.setDateHeader(
						"
						Expires
						"
						, 
						0
						);
            response.setDateHeader(
						"
						Expires
						"
						, 
						0
						);
						11
						
								 response.setContentType(getContentTypeByFileExt(fileName.substring(fileName.lastIndexOf(
						"
						.
						"
						))));
            response.setContentType(getContentTypeByFileExt(fileName.substring(fileName.lastIndexOf(
						"
						.
						"
						))));
						12
						
								 
            
						13
						
								 ServletOutputStream out 
						=
						 response.getOutputStream();
            ServletOutputStream out 
						=
						 response.getOutputStream();            
						14
						
								 InputStream in 
						=
						 
						new
						 FileInputStream(file);
            InputStream in 
						=
						 
						new
						 FileInputStream(file);
						15
						
								 BufferedInputStream bis 
						=
						 
						new
						 BufferedInputStream(in);
            BufferedInputStream bis 
						=
						 
						new
						 BufferedInputStream(in);
						16
						
								 BufferedOutputStream bos 
						=
						 
						new
						 BufferedOutputStream(out);
            BufferedOutputStream bos 
						=
						 
						new
						 BufferedOutputStream(out);
						17
						
								 byte
						[] buff 
						=
						 
						new
						 
						byte
						[
						2048
						];
            
						byte
						[] buff 
						=
						 
						new
						 
						byte
						[
						2048
						];
						18
						
								 int
						 bytesRead;
            
						int
						 bytesRead;
						19
						
								 
								 while
						 (
						-
						1
						 
						!=
						 (bytesRead 
						=
						 bis.read(buff, 
						0
						, buff.length)))
            
						while
						 (
						-
						1
						 
						!=
						 (bytesRead 
						=
						 bis.read(buff, 
						0
						, buff.length))) 
						
								 {
						
						
								{
								20
								
										 bos.write(buff, 
								0
								, bytesRead);
                bos.write(buff, 
								0
								, bytesRead);
								21
								
										 }
            }
						
						
								
						
						22
						
								 
								 if
						 (bis 
						!=
						 
						null
						)
            
						if
						 (bis 
						!=
						 
						null
						) 
						
								 {
						
						
								{
								23
								
										 bis.close();
                bis.close();
								24
								
										 }
            }
						
						
								
						
						25
						
								 
								 if
						 (bos 
						!=
						 
						null
						)
            
						if
						 (bos 
						!=
						 
						null
						) 
						
								 {
						
						
								{
								26
								
										 bos.close();
                bos.close();
								27
								
										 }
            }
						
						
								
						
						28
						
								 
								 }
				
				 
				else
        }
				
				 
				else
				 
				
						 {
				
				
						{
						29
						
								 throw
						 
						new
						 FileNotFoundException(fileName);
            
						throw
						 
						new
						 FileNotFoundException(fileName);
						30
						
								 }
        }
				
		 
		上述改动已经提交给了FCKeditor,如果大家真的有兴趣,可以去找里面我所提交的patch。
二、至于上述的2、3问题,同样,动手即可解决,在此略过。
过程中倒是碰到几个有意思的问题,成了花絮,其实也是使用FCKeditor的一些心得,写写可能还有点意思:
1、如何取得FCKeditor的值?
答案:这是我们常常干的事情:取得这个值并赋值给某个hidden,再合法性检查+submit等。怎么取得呢?这样:
		
				1
				 var
				 oEditor 
				=
				 FCKeditorAPI.GetInstance('editor') ;
				    
				var
				 oEditor 
				=
				 FCKeditorAPI.GetInstance('editor') ;
				2
				
						 //
				Get the editor contents in XHTML.
    
				//
				Get the editor contents in XHTML.
				
						
				
				3
				
						 //
				alert( oEditor.GetXHTML(true) ) ;    // "true" means you want it formatted.
				
				    
				//
				alert( oEditor.GetXHTML(true) ) ;    // "true" means you want it formatted.
				
						
				
				4
				
						 document.all(
				"
				tip.c_content
				"
				).value
				=
				oEditor.GetXHTML(
				true
				);
				
				    document.all(
				"
				tip.c_content
				"
				).value
				=
				oEditor.GetXHTML(
				true
				);
		 
		2、如何使得FCKeditor接收tab键?
答案:我们希望界面元素按照外面的安排进行tab切换,但FCKeditor怎么能做到呢?也有办法:
		
				1
				 
				 function
				 focusIframeOnTab(caller, tabTargetId, callEvent)
				function
				 focusIframeOnTab(caller, tabTargetId, callEvent)
				
						 {
				
				
						{
						2
						
								 //
						 If keypress TAB and not SHIFT+TAB
                
						//
						 If keypress TAB and not SHIFT+TAB 
						
								
						
						3
						
								 if
						(callEvent.keyCode 
						==
						 
						9
						 
						&&
						 
						!
						callEvent.shiftKey)
						
						                
						if
						(callEvent.keyCode 
						==
						 
						9
						 
						&&
						 
						!
						callEvent.shiftKey)
						4
						
								 document.getElementById(tabTargetId).contentWindow.focus();
                    document.getElementById(tabTargetId).contentWindow.focus();
						5
						
								 }
            }
				
		 
		光光有个函数顶个什么用,还要这样:在之前的那个界面元素中加上下面的事件,如使用struts的tag的化,这样就可以了:
		
				 <
				html:text 
				property
				="tip.c_title"
				 style
				="width:450px"
				 tabindex
				="1"
				 onkeydown
				="focusIframeOnTab(this, 'editor___Frame',event);if(!document.all) return false;"
				/>
				<
				html:text 
				property
				="tip.c_title"
				 style
				="width:450px"
				 tabindex
				="1"
				 onkeydown
				="focusIframeOnTab(this, 'editor___Frame',event);if(!document.all) return false;"
				/>
		 
		这点是google了半天最终在FCKeditor的FAQ中找到的,看来以后用开源的软件第一件事情就是看FAQ,错不了!
3、如何希望在FCKeditor加载完毕后做点什么事情?
答案:也很简单,编写自己的FCKeditor_OnComplete函数,如:
		
				 
				 function
				 FCKeditor_OnComplete( editorInstance )
				function
				 FCKeditor_OnComplete( editorInstance ) 
				
						 {
				
				
						{
 window.status 
						=
						 editorInstance.Description ;
                window.status 
						=
						 editorInstance.Description ;
 }
            }
				
		 
		
				
4、如果在图片、FLASH等界面中上载了东西后,希望能告诉自己的表单,怎么做?
答案:这个花了我不少看代码和调试时间!其实这里的关键就是如何获取嵌入FCKeditor的那个window,这样就可以了,在对应的js文件(如editor\dialog\fck_image\fck_image.js)中的ok方法的最后加入:
		
				 
				
						
						 //
				edit by zhengxq
    
				//
				edit by zhengxq
				
						
						 
						 try
				
				    
				try
				
						 {
				
				
						{        
 var
						 obj 
						=
						 window.dialogArguments.Editor.parent.document;
        
						var
						 obj 
						=
						 window.dialogArguments.Editor.parent.document;
 obj.getElementById(
						"
						tip.c_tip_has_pic
						"
						).value 
						=
						 
						"
						1
						"
						;
        obj.getElementById(
						"
						tip.c_tip_has_pic
						"
						).value 
						=
						 
						"
						1
						"
						;

 }
				
				catch
				(e)
    }
				
				catch
				(e)
				
						 {}
				
				
						{}
				
				    
		 
		关键就是:window.dialogArguments.Editor.parent.document,这个能够找到对应窗口的引用,有了这个,还不会控制吗?!