这段时间在做一个Java Web项目需要用到CKEditor做编辑器,但这个编辑器取值和图片上传不太好弄,特别是图片上传,写篇文章纪念一下。
写在最前:Eclipse如何将项目部署到tomcat,而不是workspace的somewhere
这个很重要,不然上传的文件怎么生成URI呢?MyEclipse不知道有没有这个问题,本人没有测试。但Eclipse是默认将web项目部署到.metadata.plugins\org.eclipse.wst.server.core\tmp1\wtpwebapps下的,很无语!
-
先放一张配置好后的Server
Step 1:停掉你的Tomcat服务器,并删除当前配置的server
-
一般双击Server看到的Server Locations是灰掉的,不能操作,所以要删掉重配
Step 2:直接新建一个Server
Step 3:双击Server进行配置
- 选择Deploy path到你tomcat的webapps下
- 重新发布项目到Server就可以在tomcat的webapps下看到你的项目了。
在JSP中引入CKEditor
Step 1:首先你得需要一个CKEditor
- 去官网下载for java版本,或者用我的这个版本
链接:http://pan.baidu.com/s/1dECfVax 密码:mzbw
-
将整个文件夹拷到你得WebContent下
- 然后导入CKEditor的核心jar包,我这儿也有
链接:http://pan.baidu.com/s/1b1wEq6 密码:xd4n
Step 2:使用CKEditor
- 在合适位置(一般是在head里)引用CKEditor的JS文件
//appPath是你得项目路径,这个可以很容易获得= =不行就用相对路径试试
<script type="text/javascript" src="<%=appPath%>/ckeditor/ckeditor.js"></script>
- 遵循官网推荐的原则,使用自带的taglib
//在JSP页面的Page标签后引入
<%@ taglib uri="http://ckeditor.com" prefix="ckeditor"%>
//一般是要有form包裹起来,因为后面还要提交到服务器的
<textarea name="editor" cols="100" id="editor" rows="10"></textarea>
<ckeditor:replace replace="editor" basePath="/ckeditor/" />//这里的replace后跟的是textarea的name值
这里用的是经典的方法,利用CKEditor替换掉textarea中的值。网上也有一些使用JS来替换的,我也试了但并没有成功,还是taglib比较给力。
- 成功后页面是这样的。
- 当然你见到的这些东西都是可设置的,就在ckeditor文件夹下的config.js中,网上有太多的教程,就不说明了。这里推荐一篇超详细的配置
Step 3:重点来了,如何获得CKEditor的内容呢?
我尝试了N遍,试图直接从被替换掉的textarea中获取前台输入的内容,然而并没有成功,永远得到的都是null
- 换个思路!在前台使用一个什么来代替ckeditor框来上传到后台,赋值的事就交给JS来处理
<div class="control-group">
<input name="articleContent" id="content" type="hidden" />//中转的input框
</div>
</form>
//ckeditor框中内容并没有提交到后台
<div class="control-group">
<label>内容:</label><br />
<textarea name="editor" cols="100" id="editor" rows="10"></textarea>
<ckeditor:replace replace="editor" basePath="/ckeditor/" />
</div>
- 注意:我的textarea框在</form>后,并没有提交到后台,而是通过JS获得textarea的值再赋给隐藏的input的value
- JS赋值,下面的代码写在你提交事件的那个函数里,然后后台就可以通过获取articleContent的值来间接得到CKEditor中输入的值了~
var value = CKEDITOR.instances.editor.getData();//固定格式,没什么毛病
$("#content").val(value);//这里用的JQuery,比较清爽= =
Step 4:该上传图片了
配置好CKEditor后,是可以直接从其他网站Copy文章(带图片)然后上传的,但是如果我的文章是原创怎么办呢,那就不得不上传图片了。尝试过去给CKEditor配它的另一半CKfinder,但没有成功,上传服务器那一下总是出错。此路不通,只有绕行~
思路:利用Struts2的图片上传绑定到CKEditor
- 首先,你得有上传这个功能(默认是没有的!),找到WebContent\ckeditor\plugins\image\dialogs目录下的image.js,搜索upload,将hidden改为false或0,这样点击图像就能看到上传功能了。
- 然后,写一个Struts2上传文件(图片)的功能,擢这里参考人家写好的代码,比较详细但只取Action与Util类以及action配置就好,其它的有些问题,需要做些小修改。
- 导入文章中的代码后,小修改下
//some code
//修改编码为UTF-8,其实这儿GBK也没什么不可,我强迫症!
response.setCharacterEncoding("UTF-8");
//some code
//修改上传路径(物理路径),到Apache tomcat下面的webapps文件中的一个目录(便于给URL),这样重新部署时之前上传的文件就不会被删除
String uploadPath = "C:\\AllProjects\\apache-tomcat\\webapps\\uploads\\"+DateUtil.getDirDate()+"\\";
//修改返回图像URL到你刚刚指定的目录
out.println("window.parent.CKEDITOR.tools.callFunction(" + callback + ",'" + "http://localhost:8080/uploads/"+ DateUtil.getDirDate() +"/"+ fileName + "','')");
- 配置Struts的Action。
<action name="uploadfile" class="com.xxx.web.action.CkeditorUploadAction"></action>
这里要是运行报错,可能就是action配置的namespace错了,根据报错将action配置到指定的namespace就好
- 最后,绑定CKEditor的上传事件到刚刚的action,打开CKEditor的config.js加入下面这一句
config.filebrowserUploadUrl = 'uploadfile';//这个uploadfile是你刚刚的Action的name
16.04.24更新
- 之前的部分只能实现简单的图片上传,需求不止于此。如果要上传附件(即不止是图片,可能是任何文件),该怎么办呢。这里需要对上传Action进行处理下,并且将Struts2的上传文件大小限制调整到适合大小即可。
step 1:对原来的上传Action进行处理
package com.xxx.action;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts2.ServletActionContext;
import util.DateUtil;
import com.opensymphony.xwork2.ActionSupport;
public class CkeditorUploadAction extends ActionSupport{
private File upload;
private String uploadContentType;
private String uploadFileName;
public File getUpload() {
return upload;
}
public void setUpload(File upload) {
this.upload = upload;
}
public String getUploadContentType() {
return uploadContentType;
}
public void setUploadContentType(String uploadContentType) {
this.uploadContentType = uploadContentType;
}
public String getUploadFileName() {
return uploadFileName;
}
public void setUploadFileName(String uploadFileName) {
this.uploadFileName = uploadFileName;
}
public String execute() throws Exception {
HttpServletResponse response = ServletActionContext.getResponse();
response.setCharacterEncoding("UTF-8");
PrintWriter out = response.getWriter();
// CKEditor提交的很重要的一个参数
String callback = ServletActionContext.getRequest().getParameter("CKEditorFuncNum");
InputStream is = new FileInputStream(upload);
// String uploadPath = ServletActionContext.getServletContext().getRealPath("uploads/"+DateUtil.getDirDate());//这个目录是在你的项目下
String uploadPath = "C:\\AllProjects\\apache-tomcat\\webapps\\uploads\\"+DateUtil.getDirDate()+"\\";//这里改成tomcat下的webapps下
System.out.println("uploadpath:"+uploadPath);
File dirfile=new File(uploadPath);
if(!dirfile.exists()){
dirfile.mkdirs();
}
System.out.println("filename:"+uploadFileName);//直接使用上传文件的名字,没有重新命名了= =偷懒,但也有好处
File toFile = new File(uploadPath, uploadFileName);
OutputStream os = new FileOutputStream(toFile);
byte[] buffer = new byte[1024];
int length = 0;
while ((length = is.read(buffer)) > 0) {
os.write(buffer, 0, length);
}
is.close();
os.close();
// 返回“图像”选项卡并显示图片
out.println("<script type=\"text/javascript\">");
out.println("window.parent.CKEDITOR.tools.callFunction(" + callback + ",'" + "http://localhost:8080/uploads/"+ DateUtil.getDirDate() +"/"+ uploadFileName + "','')");
out.println("</script>");
return null;
}
}
Step 2:修改struts.properties
- 在struts.properties将struts.multipart.maxSize改为适当的大小,默认为2M,一般不适用
struts.multipart.maxSize=52428800 <!-- 这里是50M,单位是Byte,根据需要调整->
生命不息,折腾不止