本文介绍FCKeditor在Java环境下的使用方法。
一、简介
功能:所见即所得,支持图片和Flash,工具栏可自由配置,使用简单 兼容性:IE 5.5+、Firefox 1.5+、Safari 3.0+、Opera 9.50+、Netscape 7.1+、 Camino 1.0+ 成熟度:使用广泛,被Baidu、CSDN等选用 二、下载 官方下载首页:http://www.fckeditor.net/download / ,当前版本为2.6Beta,需要下载FCKeditor 2.6Beta(FCKeditor_2.6b.zip )和FCKeditor.Java(FCKeditor-2.3.zip )。 三、部署
本例以WebRoot作为应用根路径,部署后的目录结构如下图所示:
1、FCKeditor_2.5.1.zip解压,将fckeditor文件夹复制到/WebRoot/下
2、 FCKeditor-2.3.zip解压,将commons-fileupload.jar和FCKeditor-2.3.jar复制到/WebRoot /WEB-INF/lib/下,将src下面的FCKeditor.tld复制到/WebRoot/WEB-INF/下,把src目录下的java类的复 制到project的src目录下
3、修改/WebRoot/WEB-INF/web.xml文件,只定义了两个Servlet映射,并 且对上传文件的目录和允许哪些文件上传、拒绝哪些文件上传做了设置,请注意,这两个servlet的url-pattern我都在原来代码的前面加上了 /fckeditor,这是表示FCKeditor的根目录。另外SimpleUploader中的enabled属性要改成true,允许上传,增加内 容如下:
<
servlet
>
<
servlet-name
>
Connector
</
servlet-name
>
<
servlet-class
>
com.fredck.FCKeditor.connector.ConnectorServlet
</
servlet-class
>
<
init-param
>
<
param-name
>
baseDir
</
param-name
>
<
param-value
>
/UserFiles/
</
param-value
>
</
init-param
>
<
init-param
>
<
param-name
>
debug
</
param-name
>
<
param-value
>
true
</
param-value
>
</
init-param
>
<
load-on-startup
>
1
</
load-on-startup
>
</
servlet
>
<
servlet
>
<
servlet-name
>
SimpleUploader
</
servlet-name
>
<
servlet-class
>
com.fredck.FCKeditor.uploader.SimpleUploaderServlet
</
servlet-class
>
<
init-param
>
<
param-name
>
baseDir
</
param-name
>
<
param-value
>
/UserFiles/
</
param-value
>
</
init-param
>
<
init-param
>
<
param-name
>
debug
</
param-name
>
<
param-value
>
true
</
param-value
>
</
init-param
>
<
init-param
>
<
param-name
>
enabled
</
param-name
>
<
param-value
>
true
</
param-value
>
</
init-param
>
<
init-param
>
<
param-name
>
AllowedExtensionsFile
</
param-name
>
<
param-value
></
param-value
>
</
init-param
>
<
init-param
>
<
param-name
>
DeniedExtensionsFile
</
param-name
>
<
param-value
>
php|php3|php5|phtml|asp|aspx|ascx|jsp|cfm|cfc|pl|bat|exe|dll|reg|cgi
</
param-value
>
</
init-param
>
<
init-param
>
<
param-name
>
AllowedExtensionsImage
</
param-name
>
<
param-value
>
jpg|gif|jpeg|png|bmp
</
param-value
>
</
init-param
>
<
init-param
>
<
param-name
>
DeniedExtensionsImage
</
param-name
>
<
param-value
></
param-value
>
</
init-param
>
<
init-param
>
<
param-name
>
AllowedExtensionsFlash
</
param-name
>
<
param-value
>
swf|fla
</
param-value
>
</
init-param
>
<
init-param
>
<
param-name
>
DeniedExtensionsFlash
</
param-name
>
<
param-value
></
param-value
>
</
init-param
>
<
load-on-startup
>
1
</
load-on-startup
>
</
servlet
>
<
servlet-mapping
>
<
servlet-name
>
Connector
</
servlet-name
>
<
url-pattern
>
/ fckeditor/editor/filemanager/browser/default/connectors/jsp/connector
</
url-pattern
>
</
servlet-mapping
>
<
servlet-mapping
>
<
servlet-name
>
SimpleUploader
</
servlet-name
>
<
url-pattern
>
/ fckeditor/editor/filemanager/upload/simpleuploader
</
url-pattern
>
</
servlet-mapping
>
4、修改/WebRoot/fckeditor/fckconfig.js,修改部分如下:
FCKConfig.BasePath + "filemanager/browser/default/browser.html?Connector=connectors/jsp/connector" ; FCKConfig.BasePath + "filemanager/browser/default/browser.html?Type=Image&Connector=connectors/jsp/connector" ; FCKConfig.BasePath + "filemanager/browser/default/browser.html?Type=Flash&Connector=connectors/jsp/connector" ; FCKConfig.BasePath + 'filemanager/upload/simpleuploader?Type=File' ; FCKConfig.BasePath + 'filemanager/upload/simpleuploader?Type=Image' ; FCKConfig.BasePath + 'filemanager/upload/simpleuploader?Type=Flash' ;
注意 :步骤 3、4设置了文件浏览和上传的配置,web.xml中Servlet的<url-pattern>要和fckconfig.js中的URL引 用一致。另外,我也把FCKeditor目录\fckeditor\editor\filemanager\下的connectors文件夹移到了 \fckeditor\editor\filemanager\browser\default\目录下,我也不知道这样做有什么用处,但好像不这样做就 会发生错误,希望大家指教。
四、使用 本例使用最直接的js方式,API和TagLib方式参见FCKeditor-2.3.zip解压后_samples下的例子。 fckdemo.jsp:
<%
@ page contentType
=
"
text/html;charset=GBK
"
%>
<
html
>
<
head
>
<
title
>
FCKeditor Test
</
title
>
<
script
type
="text/javascript"
src
="fckeditor/fckeditor.js"
></
script
>
</
head
>
<
body
>
<
form
action
="fckdemo.jsp"
method
="post"
>
<%
String
content
=
request.getParameter(
"
content
"
);
%>
<
table
width
=80%
>
<
tr
>
<
td
colspan
=4
style
='text-align:center'
>
<
span
>
<
script
type
="text/javascript"
>
var
oFCKeditor
=
new
FCKeditor('content');
//
表单的name,取值的依据
oFCKeditor.BasePath
=
'
fckeditor
/
';
//
指定FCKeditor根路径,也就是fckeditor.js所在的路径
oFCKeditor.Height
=
'200
';/ /指定高度 oFCKeditor.ToolbarSet
=
'Demo';
//
指定工具栏,这里使用了自定义的
oFCKeditor.Value
=
"
<%=content==null?
""
:(content.replaceAll(
"
\
""
,
"
'
"
))
%>
"
;// 默认值 oFCKeditor.Create(); </script> </span> </td> </tr> <tr><td align=center><input type=
"
submit
"
value=
"
提交
"
></td></tr> <tr><td> </td></tr> <tr><td>取值(可直接保存至数据库):</td></tr> <tr><td style=
"
padding:10px;
"
><%=content%></td></tr> </table>
</form> </body> </html>
效果图:
其实,我们也可以抛开JavaScript,而在服务器端使用标签来创建Web编辑器了。先在fckdemo.jsp:中引入标签库:
<%
@ taglib uri = " http://fckeditor.net/tags-fckeditor " prefix = " FCK "
%>
再在原来放JavaScript的地方,放如下代码:
这里有一点一定要注意,那就是这里的属性都要避免使用相对路径。 刷新页面,又见编辑器,此时,可以顺利的上传文件了。整合编辑器的任务到此完成。 下一步,就是怎样对编辑器进行更多的控制了。
五、配置文件fckconfig.js 1、DefaultLanguage:缺省语言,可更改为“zh-cn”
2、添加常用的中文字体:在上面打开的文件中找到
FCKConfig.FontNames
=
'Arial;Comic Sans MS;Courier New;Tahoma;Times New Roman;Verdana' ;
加上几种我们常用的字体
FCKConfig.FontNames
=
'宋体;黑体;隶书;楷体_GB2312 ;Arial;Comic Sans MS;Courier New;Tahoma;Times New Roman;Verdana' ;
3、自定义工具栏:可修改或增加ToolbarSets,例如:
FCKConfig.ToolbarSets[
"
Demo
"
]
=
[ ['Bold','Italic','
-
','OrderedList','UnorderedList','
-
','Link','Unlink','
-
','TextColor','BGColor','
-
','Style','
-
','Image','Flash','Table'] ] ;
4、EnterMode和ShiftEnterMode:“回车”和“Shift+回车”的换行行为,注释提示了可选模式
5、EditorAreaCss:编辑区样式文件
6、其他参数:
AutoDetectLanguage
=
true/false 自动检测语言 BaseHref
=
""
相对链接的基地址 ContentLangDirection
=
"
ltr/rtl
"
默认文字方向 ContextMenu
=
字符串数组
,
右键菜单的内容 CustomConfigurationsPath
=
""
自定义配置文件路径和名称 Debug
=
true/false 是否开启调试功能
,
这样
,
当调用FCKDebug.Output()时
,
会在调试窗中输出内容 EnableSourceXHTML
=
true/false 为TRUE时
,
当由可视化界面切换到代码页时
,
把HTML处理成XHTML EnableXHTML
=
true/false 是否允许使用XHTML取代HTML FillEmptyBlocks
=
true/false 使用这个功能
,
可以将空的块级元素用空格来替代 FontColors
=
""
设置显示颜色拾取器时文字颜色列表 FontFormats
=
""
设置显示在文字格式列表中的命名 FontNames
=
""
字体列表中的字体名 FontSizes
=
""
字体大小中的字号列表 ForcePasteAsPlainText
=
true/false 强制粘贴为纯文本 ForceSimpleAmpersand
=
true/false 是否不把&符号转换为XML实体 FormatIndentator
=
""
当在源码格式下缩进代码使用的字符 FormatOutput
=
true/false 当输出内容时是否自动格式化代码 FormatSource
=
true/false 在切换到代码视图时是否自动格式化代码 FullPage
=
true/false 是否允许编辑整个HTML文件
,
还是仅允许编辑BODY间的内容 GeckoUseSPAN
=
true/false 是否允许SPAN标记代替B
,
I
,
U标记 IeSpellDownloadUrl
=
""
下载拼写检查器的网址 ImageBrowser
=
true/false 是否允许浏览服务器功能 ImageBrowserURL
=
""
浏览服务器时运行的URL ImageBrowserWindowHeight
=
""
图像浏览器窗口高度 ImageBrowserWindowWidth
=
""
图像浏览器窗口宽度 LinkBrowser
=
true/false 是否允许在插入链接时浏览服务器 LinkBrowserURL
=
""
插入链接时浏览服务器的URL LinkBrowserWindowHeight
=
""
链接目标浏览器窗口高度 LinkBrowserWindowWidth
=
""
链接目标浏览器窗口宽度 Plugins
=
object 注册插件 PluginsPath
=
""
插件文件夹 ShowBorders
=
true/false 合并边框 SkinPath
=
""
皮肤文件夹位置 SmileyColumns
=
12
图符窗列数 SmileyImages
=
字符数组 图符窗中图片文件名数组 SmileyPath
=
""
图符文件夹路径 SmileyWindowHeight 图符窗口高度 SmileyWindowWidth 图符窗口宽度 SpellChecker
=
"
ieSpell/Spellerpages
"
设置拼写检查器 StartupFocus
=
true/false 开启时FOCUS到编辑器 StylesXmlPath
=
""
设置定义CSS样式列表的XML文件的位置 TabSpaces
=
4
TAB键产生的空格字符数 ToolBarCanCollapse
=
true/false 是否允许展开/折叠工具栏 ToolbarSets
=
object 允许使用TOOLBAR集合 ToolbarStartExpanded
=
true/false 开启是TOOLBAR是否展开 UseBROnCarriageReturn
=
true/false 当回车时是产生BR标记还是P或者DIV标记
六、自定义样式 工具栏的Style选项,是由fckconfig.js指定的配置文件来产生的:
FCKConfig.StylesXmlPath
=
FCKConfig.EditorPath
+
'fckstyles.xml' ;
可修改fckstyles.xml来自定义样式。 七、如何获取编辑器中插入的图片
从文章开头的功能设计我们可以看出,当用户编辑完文章后,我们应该能获取文章中插入的图片信息。怎样获取编辑器中的插入的图片呢?IT进行时 在他的文章FCKeditor的几点重要改进和使用心得,值得分享 中是这样做的:在上传图片的对话框的JavaScript中添加代码,使得当用户插入图片点OK后通知列表框,代码如下:
try { var obj = window.dialogArguments.Editor.parent.document; obj.getElementById( " tip.c_tip_has_pic " ).value = " 1 " ; } catch (e) {
}
我认为这个方法不好,第一,这个方法是侵入性的,需要修改FCKeditor的代码;第二,这种方法能够在用户插入图片的时候获得图片信息,但是如果用户插入的图片,接着又把图片从文章中删除了呢?这时候是无法跟踪的。
正确的思路应该是在编辑器失去焦点的时候,获取编辑器中的文档,通过DOM取得文章中所有的图片。代码如下:
function
FCKeditor_OnComplete( editorInstance )
{ editorInstance.Events.AttachEvent( 'OnBlur', onEditorBlur ) ; }
function
onEditorBlur()
{ var oSelect = $( " img_select " ); for ( var i = oSelect.options.length - 1 ; i > 0 ; i -- ) { oSelect.options[i] = null ; } oEditor = FCKeditorAPI.GetInstance('EditorDefault'); var imgs = oEditor.EditorDocument.body.all.tags( " img " ); for ( var i = 0 ; i < imgs.length; i ++ ) { var oOption = document.createElement( " option " ); oOption.appendChild(document.createTextNode(imgs[i].src)); oSelect.appendChild(oOption); } }
八、如何给每一个用户分配一个单独的目录用来保存用户上传的图片。
经过我对FCKeditor的文档的反复阅读,发现FCKeditor自带的API没有办法实现这样的功能,所以,修改的重点还是在FCKeditor.java中。我们可以对源代码进行如下修改: 1、打开FCKeditor-2.3\src\com\fredck\FCKeditor\uploader目录下的SimpleUploaderServlet.java文件,找到SimpleUploaderServlet类的doPost方法,它的代码如下:
public
void
doPost(HttpServletRequest request, HttpServletResponse response)
throws
ServletException, IOException {
if
(debug) System.out.println(
"
--- BEGIN DOPOST ---
"
);
response.setContentType(
"
text/html; charset=UTF-8
"
); response.setHeader(
"
Cache-Control
"
,
"
no-cache
"
); PrintWriter out
=
response.getWriter();
String typeStr
=
request.getParameter(
"
Type
"
); String currentPath
=
baseDir
+
typeStr;
String userName
=
request.getSession().getUser().getName(); currentPath
=
currentPath
+
userName
+
"
/
"
; String currentDirPath
=
getServletContext().getRealPath(currentPath); currentPath
=
request.getContextPath()
+
currentPath;
if
(debug) System.out.println(currentDirPath); String retVal
=
"
0
"
; String newName
=
""
; String fileUrl
=
""
; String errorMessage
=
""
;
if
(enabled) { DiskFileUpload upload
=
new
DiskFileUpload();
try
{ List items
=
upload.parseRequest(request); Map fields
=
new
HashMap(); Iterator iter
=
items.iterator();
while
(iter.hasNext()) { FileItem item
=
(FileItem) iter.next();
if
(item.isFormField()) fields.put(item.getFieldName(),item.getString());
else
fields.put(item.getFieldName(),item); } FileItem uplFile
=
(FileItem)fields.get(
"
NewFile
"
); String fileNameLong
=
uplFile.getName(); fileNameLong
=
fileNameLong.replace(
'
\
'
,
'
/
'
); String[] pathParts
=
fileNameLong.split(
"
/
"
); String fileName
=
pathParts[pathParts.length
-
1
]; String nameWithoutExt
=
getNameWithoutExtension(fileName); String ext
=
getExtension(fileName); File pathToSave
=
new
File(currentDirPath,fileName); fileUrl
=
currentPath
+
"
/
"
+
fileName;
if
(extIsAllowed(typeStr,ext)) {
int
counter
=
1
;
while
(pathToSave.exists()){ newName
=
nameWithoutExt
+
"
(
"
+
counter
+
|