FCKeditor简介:
FCKeditor是一个专门使用在网页上属于开放源代码的所见即所得文字编辑器。它志于轻量化,不需要太复杂的安装步骤即可使用。它可和PHP、JavaScript、ASP、ASP.NET、ColdFusion、Java、以及ABAP等不同的编程语言相结合。“FCKeditor”名称中的“FCK” 是这个编辑器的作者的名字Frederico Caldeira Knabben的缩写。FCKeditor 相容于绝大部分的网页浏览器.
如果要将fckeditor跑起来,首先需要jar包,还有FCKeditor_2.6.4.1.zip,这些大家都可以到www.fckeditor.net官方网站上下载,这里的需要的jar包我给大家列出来:
commons-fileupload-1.2.1.jar
commons-io-1.3.2.jar
fckeditor-java-core-2.4.jar
java-core-2.4.jar
slf4j-api-1.5.2.jar
slf4j-simple-1.5.2.jar
csdn上还有资源,大家都可以去下载
接下来如何调用fckeditor呢?有两种方式:通过javascript调用和jsp的自定义的标签来使用
将解压后的FckEditor_2.6.3放在web 工程的webroot下面
然后新建一个html,在其中引入fckeditor文件夹中的fckeditor.js,引入如下:<script type="text/javascript" src="fckeditor/fckeditor.js">
接下来:介绍第一种方法:
<script type="text/javascript">
var fckeditor=new FCKeditor('FCKeditor1');//新建一个fckeditor实例
fckeditor.BasePath="/fckeditor/";//设置编辑器的位置,该位置一定要以/结尾,这个basepath是指fckeditor文件夹下所有文件的地址,默认值是这个,但是我们一般前面还要加上工程的名字,如/prj/fckeditor/这样
fckeditor.Create();//创建并且调用一个fckeditor编辑器
</script>
第二种方法:通过jsp自定义标签来完成调用
可以参考:
@演示工程fckeditor-java-demo-2.4.war :jsp文件夹--》sample02.html
@fckeditor-java-2.4文档
<%@ taglib="http://java.fckeditor.net"%>
<FCK:editor instanceName="myEditor" basePath="/fckeditor" value="this is value"></FCK:editor><!--注意这里必须写value值,并且值不能为空字符串-->
注意:basePath以/开头,并且这个/代表当前工程的路径
完成上述步骤后,即可通过浏览器访问该html文件了,大家就可以看到一个简单的fckeditor界面了,但是很多东西还是需要自己配置才能使用的
首先大家可以去www.fckeditor.net官方网站上下载fckeditor-java-demo-2.4.war然后直接丢到tomcat中,即可在浏览器中浏览页面http://localhost:8080/fckeditor-java-demo-2.4/
还要下载FCKeditor_2.6.4.1.zip和fckeditor-java-2.4-bin.zip
配置——使用配置文件
fckconfig.js即主配置文件,如果我们要修改配置,就需要修改该文件中的属性,一般我们可以直接修改该配置文件,不过我们不采取这样的做法,一般我们是新建一个配置文件myconfig。js来覆盖默认的配置文件
比如,我们新建了一个myconfig.js然后在里面写上FCKConfig.AutoDetectLanguage=false;FCKConfig.DefaultLanguage='fr'将原本配置文件中的自动发现语言改为false,并指定默认的语言为法语 fr
那么当我们写完配置文件后,如果应用呢?有两种方法:
1)在原本的配置文件中fckconfig.js中的 FCKConfig.CustomConfigurationPath=''改为FCKConfig.CustomConfigurationPath='/fck/myconfig.js'
注意:这种方法会修改所有的关于fckeditor页面的属性
2)在页面中来制定。在调用fck的 代码中添加如下语句:fckeditor.Config["CustomConfigurationsPath"]="/test/myconfig.js";
注意:这种方法只会修改所在页面的fckeditor的属性,一般工程发布的时候不确定在哪,所以test应跟换为FCKeditor.EditorPath,它指的是 fckeditor文件夹下的editor文件夹
总结一下配置fckeditor:
1)直接修改主配置文件,fckconfig.js
2)定义单独的配置文件(只需要写需要修改的配置项)
3)在页面的代码中对FCKeditor的实例进行配置
配置加载顺序:
1)加载主配置文件fckconfig.js
2)加载自定义的配置文件(如果有),覆盖相同的配置项(注意是相同的)
3)使用对实例的配置覆盖相同的配置项(只对当前实例有效)
注意事项:
1.永远都不要删除主配置文件:fckconfig.js
2.系统会自动侦测并运行适当的界面语言(默认,可以修改)
3.修改配置后要清空浏览器缓存,以免影响结果(或访问时强制刷新也可以)
一般需要修改的配置
1)自定义ToolbarSet,去掉一些功能
2)加上几种常用的字体
3)修改“回车”和“shift+回车”的换行行为:原本fck的回车键的效果是换段落,而shift+回车的效果是换行,所以我们要将这两种效果颠倒一下
4)修改编辑区样式文件
5)更换表情图片
关于设置ToolbarSet:首先在fckconfig.js找到FCKConfig.ToolbarSets[]中括号中可以指定toolbar的名字,比如mytoolbar,然后在调用fck的页面设置一下toolbarset为mytoolbar即fckeditor.ToolbarSet="mytoolbar",这样就可以了
关于加上几种字体:只需要FCKConfig.FontNames中添加我们想添加的字体,注意它会提示不让保存,则设置myconfig.js文件properties的resources选项中的text file encoding ,只能设置为utf-8
关于修改回车换行换段:
FCKConfig.ShiftEnterMode = 'p' ; // p | div | br
FCKConfig.EnterMode = 'br' ; // p | div | br
改成这样,原本是将两行互相调换的
关于编辑区样式文件:在主配置文件fckconfig.js文件中,找到FCKConfig.EditorAreaCSS = FCKConfig.BasePath + 'css/fck_editorarea.css' ;
我们会发现所有的样式都是在editor文件夹下的css文件夹下的fck_editorarea.css文件中的,
关于添加自定义表情:
FCKConfig.SmileyPath = FCKConfig.BasePath + 'images/smiley/msn/' ;//表示表情图片所在文件夹
FCKConfig.SmileyImages = ['regular_smile.gif','sad_smile.gif','wink_smile.gif','teeth_smile.gif','confused_smile.gif','tounge_smile.gif','embaressed_smile.gif','omg_smile.gif','whatchutalkingabout_smile.gif','angry_smile.gif','angel_smile.gif','shades_smile.gif','devil_smile.gif','cry_smile.gif','lightbulb.gif','thumbs_down.gif','thumbs_up.gif','heart.gif','broken_heart.gif','kiss.gif','envelope.gif'] ;//文件夹中的每幅图片,其内容是个数组
FCKConfig.SmileyColumns = 8 ;//表示每列显示的表情图片数
FCKConfig.SmileyWindowWidth= 320 ;//表示弹出的对话框的宽度
FCKConfig.SmileyWindowHeight= 210 ;//表示弹出的对话框的高度
如果我们想将自己的一副图片加入到表情中,则首先将图片copy到文件夹中,然后再数组中加入该图片的名字,即可
也可以将自己的一个图片文件夹作为表情图片文件夹,则需要指定SmileyPath为我们自己的图片文件夹,然后将文件夹中每个图片名称罗列在数组中
这时我们可能遇到,如果图片太多,则会显示的很长很长,即使我们设置了SmileyWindowWidth和SmileyWindowHeight也没有用,这时我们右击,查看其源文件,应该是http://localhost:8080/fck/fckeditor/editor/dialog/fck_smiley.html这个html,然后我们找到打开,window.onload事件中dialog.SetAutoSize(true) ;我们将它改为false,这样就会按照我们指定的宽高来显示了,可是会少了很多图片表情,所以我们还要在<body style="overflow: hidden">这里,将hidden改为scroll,如果图片过多在指定的宽高无法显示,则会自动添加滚动条
最后提示、:FCKConfig.BasePath和调用fckeditor时指定的BasePath(FCKeditor BathPath)不是同一个,其值也不一样
文件上传:这是很常用的
我们可以参照D:/JAVA/FCKeditor/fckeditor-java-2.4-bin/fckeditor-java-2.4/site/connector.html,该文件,
第一步:
Declare the ConnectorServlet in your web.xml
<web-app version="2.4">
<servlet>
<servlet-name>Connector</servlet-name>
<servlet-class>
net.fckeditor.connector.ConnectorServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Connector</servlet-name>
<url-pattern>
/fckeditor/editor/filemanager/connectors/*
</url-pattern>
</servlet-mapping>
</web-app>
配置文件
第二步:
在工程的src下新建一个fckeditor.properties文件,文件内容如下:
connector.userActionImpl=net.fckeditor.requestcycle.impl.UserActionImpl
这样就可以简单使用上传了
在上传文件名为中文的时候会出现名称会出现乱码,如何解决?
首先要知道这个乱码可能是提交的内容是否出现不正确的编码问题,或者是提交至服务器端处理时出现的问题
首先我们找到对应的editor->filemanager->default->frmupload.html我们发现它是以utf-8的编码显示的,没有任何问题,接着我们看爱你给哪个文件处理的,就在我们刚配置的web.xml文件中已经指定了net.fckeditor.connector.ConnectorServlet,是这个,这个servlet在referenced libraries下面的fckeditor-java-core。jar包下的net。fckeditor。connector下的servlet,然后我们要attach source,关联上源码,源码是fckeditor-java-2.4-src.zip,完了之后,按ctrl+o,然后看它的dopost方法,在List<FileItem> item=upload.parseRequest(request);这里是需要指定编码的。但这个文件我们修改不了,所以要复制过来,在src下新建一个package,新建同样名称的servlet,然后粘贴,在try之前写上:upload.setHeaderEncoding("utf-8");接着必须要在web.xml文件中修改
<servlet-class>
net.fckeditor.connector.ConnectorServlet修改这里,将前面的包名给改了
</servlet-class>
除此之外,还会在创建中文目录名时出现乱码
仍然在ConnectorServlet文件中在doget方法中,找到NewFoldName,然后添上:
String tempstr=request.getParameter("NowFoldName");
tempstr=new String(temstr.getBytes("iso8859-1"),"utf-8");
String newFoldStr=……(tempstr)
引用中文名称的图片不能正常显示?
方法一:修改tomcat连接器的配置:tomcat6.0-->conf-->server.xml-->
<Connector executor="tomcatThreadPool"
port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"
在这个后面增加一个属性:URIEncoding="utf-8"
修改完后,需要重新启动tomcat服务器,不过该种方法不推荐使用
方法二:避免使用中文名称的图片,即在对中文名称的图片进行保存时,让其不以中文形式保存,改以uuid编码方式
在ConnectorServlet文件中,dopost方法中找到保存文件的地方,pathToSave然后添加如下:
filename=UUID.randomUUID().toString()+"."+extension;
以上讲述比较理论,大家可以我已经配置好的ConnectorServlet类,代码如下:
package net; import java.io.*; import javax.servlet.*; import javax.servlet.http.*; import java.util.*; import java.util.regex.Pattern; import org.apache.commons.fileupload.*; import javax.xml.parsers.*; import org.w3c.dom.*; import javax.xml.transform.*; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; public class ConnectorServlet extends HttpServlet { private static String baseDir; private static boolean debug = false; // 允许上传的Image类型的文件类型 private static String allowedType; // 不允许上传的File类型的文件类行 private static String unallowedFileType; /** * 初始化 servlet. * Retrieve from the servlet configuration the "baseDir" which is the root * of the file repository: * If not specified the value of "/UserFiles/" will be used. * */ public void init() throws ServletException { baseDir = getInitParameter("baseDir"); debug = (new Boolean(getInitParameter("debug"))).booleanValue(); // 设置baseDir的默认值 if (baseDir == null) baseDir = "/UserFiles/"; String realBaseDir = getServletContext().getRealPath(baseDir); File baseFile = new File(realBaseDir); // 建立目录 if (!baseFile.exists()) { baseFile.mkdir(); } // 得到允许上传的Image类型,从web.xml配置 allowedType = "|jpg|gif|jpeg|png|bmp|"; unallowedFileType = "abc"; } /** * doGet方法处理(GetFolders, GetFoldersAndFiles, CreateFolder). * 此servlet接收如下参数 * connector?Command=CommandName&Type=ResourceType&CurrentFolder=FolderPath * 它最后返回xml */ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/xml; charset=UTF-8"); response.setHeader("Cache-Control", "no-cache"); PrintWriter out = response.getWriter(); String commandStr = request.getParameter("Command"); // 得到文件类型,Image,File,Flash,Media String typeStr = request.getParameter("Type"); // 得到当前的目录 String currentFolderStr = request.getParameter("CurrentFolder"); // 得到当前目录的真实路径 String currentPath = baseDir + typeStr + currentFolderStr; String currentDirPath = getServletContext().getRealPath(currentPath); // 创建当前路径 File currentDir = new File(currentDirPath); if (!currentDir.exists()) { currentDir.mkdir(); } // 创建返回的xml文件 Document document = null; try { DocumentBuilderFactory factory = DocumentBuilderFactory .newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); document = builder.newDocument(); } catch (ParserConfigurationException pce) { pce.printStackTrace(); } Node root = CreateCommonXml(document, commandStr, typeStr, currentFolderStr, request.getContextPath() + currentPath); // 得到用户选择的目录 if (commandStr.equals("GetFolders")) { getFolders(currentDir, root, document); } // 得到用户选择的目录的文件 else if (commandStr.equals("GetFoldersAndFiles")) { getFolders(currentDir, root, document); getFiles(currentDir, root, document); } // 新建的目录 else if (commandStr.equals("CreateFolder")) { String newFolderStr = request.getParameter("NewFolderName"); //上传时,创建文件夹时出现乱码问题的解决方法 newFolderStr=new String(newFolderStr.getBytes("iso8859-1"),"UTF-8"); File newFolder = new File(currentDir, newFolderStr); System.out.println(newFolderStr+"文件夹"); String retValue = "110"; // 只能输入英文字符数字或下划线 if (!(Pattern.matches("//w+", newFolderStr))) { retValue = "102"; } // 目录已经存在 else if (newFolder.exists()) { retValue = "101"; } // 建立新目录 else { try { boolean dirCreated = newFolder.mkdir(); if (dirCreated) retValue = "0"; else retValue = "102"; } catch (SecurityException sex) { sex.printStackTrace(); retValue = "103"; } } setCreateFolderResponse(retValue, root, document); } document.getDocumentElement().normalize(); try { TransformerFactory tFactory = TransformerFactory.newInstance(); Transformer transformer = tFactory.newTransformer(); DOMSource source = new DOMSource(document); StreamResult result = new StreamResult(out); transformer.transform(source, result); if (debug) { StreamResult dbgResult = new StreamResult(System.out); transformer.transform(source, dbgResult); } } catch (Exception ex) { // ex.printStackTrace(); } out.flush(); out.close(); } /** * 处理文件上传 * * 此servlet接收如下参数: * connector?Command=FileUpload&Type=ResourceType&CurrentFolder=FolderPath */ public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html; charset=UTF-8"); response.setHeader("Cache-Control", "no-cache"); PrintWriter out = response.getWriter(); String commandStr = request.getParameter("Command"); // 得到文件类型,Image,File,Flash,Media String typeStr = request.getParameter("Type"); // 得到当前目录 String currentFolderStr = request.getParameter("CurrentFolder"); // 得到当前的真实路径 String currentPath = baseDir + typeStr + currentFolderStr; String currentDirPath = getServletContext().getRealPath(currentPath); String retVal = "0"; String newName = ""; if (!commandStr.equals("FileUpload")) retVal = "203"; else { // 产生的上传对象,并设置编译 DiskFileUpload upload = new DiskFileUpload(); upload.setHeaderEncoding("UTF-8"); 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 ext = getExtension(fileName); //为防止中文图片无法正确读取,在保存前,将图片名称改为uuid编码格式 fileName=UUID.randomUUID().toString()+"."+ext; String nameWithoutExt = getNameWithoutExtension(fileName); File pathToSave = new File(currentDirPath, fileName); System.out.println("pathToSave"+pathToSave); int counter = 1; int limitedSize=70*1024;//限制上传图片的大小 // 检查允许上传的文件类型是否为Image,是则再检查文件类型在web.xml配置 if ((this.checkImageType(allowedType, fileName)) && (typeStr.equals("Image"))) { retVal = "202"; // System.out.println("dd"); } else if ((this.checkFileType(unallowedFileType, fileName)) && (typeStr.equals("File"))) { // System.out.println("ddee"); retVal = "202"; } //如果文件大小超过限制,则返回一个自定义的错误码 else if(uplFile.getSize()>limitedSize) { retVal="204"; } else { while (pathToSave.exists()) { newName = nameWithoutExt + "(" + counter + ")" + "." + ext; newName=UUID.randomUUID().toString()+"."+ext; retVal = "201"; pathToSave = new File(currentDirPath, newName); counter++; System.out.println("namewithoutext:"+nameWithoutExt); } uplFile.write(pathToSave); } } catch (Exception ex) { ex.printStackTrace(); retVal = "203"; } } // out.println("<SCRIPT type='/"text/javascript/"'>"); out.print("<mce:script language='javascript'><!-- window.parent.frames['frmUpload'].OnUploadCompleted("+retVal + ",'" + newName + "'); // --></mce:script>"); // out.println("window.parent.frames['frmUpload'].OnUploadCompleted(" // + retVal + ",'" + newName + "');"); // out.println("</SCRIPT>"); // out.flush(); // out.close(); } private void setCreateFolderResponse(String retValue, Node root, Document doc) { Element myEl = doc.createElement("Error"); myEl.setAttribute("number", retValue); root.appendChild(myEl); } private void getFolders(File dir, Node root, Document doc) { Element folders = doc.createElement("Folders"); root.appendChild(folders); File[] fileList = dir.listFiles(); for (int i = 0; i < fileList.length; ++i) { if (fileList[i].isDirectory()) { Element myEl = doc.createElement("Folder"); myEl.setAttribute("name", fileList[i].getName()); folders.appendChild(myEl); } } } private void getFiles(File dir, Node root, Document doc) { Element files = doc.createElement("Files"); root.appendChild(files); File[] fileList = dir.listFiles(); for (int i = 0; i < fileList.length; ++i) { if (fileList[i].isFile()) { Element myEl = doc.createElement("File"); myEl.setAttribute("name", fileList[i].getName()); myEl.setAttribute("size", "" + fileList[i].length() / 1024); files.appendChild(myEl); } } } private Node CreateCommonXml(Document doc, String commandStr, String typeStr, String currentPath, String currentUrl) { Element root = doc.createElement("Connector"); doc.appendChild(root); root.setAttribute("command", commandStr); root.setAttribute("resourceType", typeStr); Element myEl = doc.createElement("CurrentFolder"); myEl.setAttribute("path", currentPath); myEl.setAttribute("url", currentUrl); root.appendChild(myEl); return root; } /** * 得到文件名,没有扩展名 * * * * @param fileName * @return */ private static String getNameWithoutExtension(String fileName) { return fileName.substring(0, fileName.lastIndexOf(".")); } /** * 得到文件的扩展名 * * @param fileName * @return */ private String getExtension(String fileName) { return fileName.substring(fileName.lastIndexOf(".") + 1); } /** * 检查上传Image类型的的文件类型,根据在web.xml配置的信息 * * * * @param type * @param fileName * @return */ private boolean checkImageType(String type, String fileName) { System.out.println(type+"type"); String[] ss = type.split("//|"); System.out.println(ss+"ss"); if (type.length() > 0) { for (int i = 0; i < ss.length; i++) { if (this.getExtension(fileName).equalsIgnoreCase(ss[i])) { return false; } // System.out.println(ss[i]); } } return true; } /** * 验证不允许上传的File类型的文件 * * * @param type * @param fileName * @return */ private boolean checkFileType(String type, String fileName) { String[] ss = type.split("//|"); if (type.length() > 0) { for (int i = 0; i < ss.length; i++) { if (this.getExtension(fileName).equalsIgnoreCase(ss[i])) { return true; } // System.out.println(ss[i]); // System.out.println(fileName); } } return false; } }