CKEditor+Struts2实现文件上传总结

这段时间在做一个Java Web项目需要用到CKEditor做编辑器,但这个编辑器取值和图片上传不太好弄,特别是图片上传,写篇文章纪念一下。

写在最前:Eclipse如何将项目部署到tomcat,而不是workspace的somewhere

这个很重要,不然上传的文件怎么生成URI呢?MyEclipse不知道有没有这个问题,本人没有测试。但Eclipse是默认将web项目部署到.metadata.plugins\org.eclipse.wst.server.core\tmp1\wtpwebapps下的,很无语!

  • 先放一张配置好后的Server


    正确配置的Server

Step 1:停掉你的Tomcat服务器,并删除当前配置的server

  • 一般双击Server看到的Server Locations是灰掉的,不能操作,所以要删掉重配


    默认的Server配置

Step 2:直接新建一个Server

点这里新建就好

Step 3:双击Server进行配置

  • 选择Deploy path到你tomcat的webapps下
重新配置Server
  • 重新发布项目到Server就可以在tomcat的webapps下看到你的项目了。

在JSP中引入CKEditor

Step 1:首先你得需要一个CKEditor

链接: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长这样
  • 当然你见到的这些东西都是可设置的,就在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,根据需要调整-> 

生命不息,折腾不止

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 201,468评论 5 473
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,620评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,427评论 0 334
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,160评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,197评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,334评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,775评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,444评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,628评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,459评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,508评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,210评论 3 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,767评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,850评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,076评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,627评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,196评论 2 341

推荐阅读更多精彩内容