`

CKEditor文件上传-多种方式-与ckfinder结合上传

阅读更多

本文介绍2种使用ckeditor上传文件保存至项目外(即硬盘)的方法。

环境:tomcat + spring

第一种:通过ckeditor+ckfinder搭配。

1)在页面中的配置

引入标签<%@ include file="/WEB-INF/jsp/layouts/taglib_ck.jsp"%>

页面html代码

<textarea name="content" id="content" rows="30"></textarea>
<hs:ckeditor replace="content" uploadPath="/cms/content" />

 

taglib_ck.jsp的内容如下:

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions"%>

<c:set var="ctx" value="${pageContext.request.contextPath}"/>
<c:set var="ctxStatic" value="${pageContext.request.contextPath}/scripts"/>

ckeditor.tag的标签如下:

<%@ tag language="java" pageEncoding="UTF-8"%>
<%@ include file="/WEB-INF/jsp/layouts/taglib_ck.jsp"%>
<%@ attribute name="replace" type="java.lang.String" required="true" description="需要替换的textarea编号"%>
<%@ attribute name="uploadPath" type="java.lang.String" required="false" description="文件上传路径,路径后自动添加年份。若不指定,则编辑器不可上传文件"%>
<script type="text/javascript">include('ckeditor_lib','${ctxStatic}/ckeditor/',['ckeditor.js']);</script>
<script type="text/javascript">
	var ${replace}Ckeditor = CKEDITOR.replace("${replace}");//<c:if test="${not empty uploadPath}">
	${replace}Ckeditor.config.ckfinderPath="${ctxStatic}/ckfinder";
	var date = new Date(), year = date.getFullYear(), month = (date.getMonth()+1)>9?date.getMonth()+1:"0"+(date.getMonth()+1);
	${replace}Ckeditor.config.ckfinderUploadPath="${uploadPath}/"+year+"/"+month+"/";//</c:if>
</script>

 ckfinder.tag的代码如下:

<%@ tag language="java" pageEncoding="UTF-8"%>
<%@ include file="/WEB-INF/jsp/layouts/taglib_ck.jsp"%>
<%@ attribute name="input" type="java.lang.String" required="true" description="输入框"%>
<%@ attribute name="type" type="java.lang.String" required="true" description="files、images、flash、thumb"%>
<%@ attribute name="uploadPath" type="java.lang.String" required="true" description="打开文件管理的上传路径"%>
<%@ attribute name="selectMultiple" type="java.lang.Boolean" required="false" description="是否允许多选"%>
<ol id="${input}Preview"></ol><a href="javascript:" onclick="${input}FinderOpen();" class="btn">${selectMultiple?'添加':'选择'}</a>&nbsp;<a href="javascript:" onclick="${input}DelAll();" class="btn">清除</a>
<script type="text/javascript">
	function ${input}FinderOpen(){//<c:if test="${type eq 'thumb'}"><c:set var="ctype" value="images"/></c:if><c:if test="${type ne 'thumb'}"><c:set var="ctype" value="${type}"/></c:if>
		var date = new Date(), year = date.getFullYear(), month = (date.getMonth()+1)>9?date.getMonth()+1:"0"+(date.getMonth()+1);
		var url = "${ctxStatic}/ckfinder/ckfinder.html?type=${ctype}&start=${ctype}:${uploadPath}/"+year+"/"+month+
			"/&action=js&func=${input}SelectAction&thumbFunc=${input}ThumbSelectAction&cb=${input}Callback&dts=${type eq 'thumb'?'1':'0'}&sm=${selectMultiple?1:0}";
		windowOpen(url,"文件管理",1000,700);
		//top.$.jBox("iframe:"+url+"&pwMf=1", {title: "文件管理", width: 1000, height: 500, buttons:{'关闭': true}});
	}
	function ${input}SelectAction(fileUrl, data, allFiles){
		var url="", files=ckfinderAPI.getSelectedFiles();
		for(var i=0; i<files.length; i++){//<c:if test="${type eq 'thumb'}">
			url += files[i].getThumbnailUrl();//</c:if><c:if test="${type ne 'thumb'}">
			url += files[i].getUrl();//</c:if>
			if (i<files.length-1) url+="|";
		}//<c:if test="${selectMultiple}">
		$("#${input}").val($("#${input}").val()+($("#${input}").val(url)==""?url:"|"+url));//</c:if><c:if test="${!selectMultiple}">
		$("#${input}").val(url);//</c:if>
		${input}Preview();
		//top.$.jBox.close();
	}
	function ${input}ThumbSelectAction(fileUrl, data, allFiles){
		var url="", files=ckfinderAPI.getSelectedFiles();
		for(var i=0; i<files.length; i++){
			url += files[i].getThumbnailUrl();
			if (i<files.length-1) url+="|";
		}//<c:if test="${selectMultiple}">
		$("#${input}").val($("#${input}").val()+($("#${input}").val(url)==""?url:"|"+url));//</c:if><c:if test="${!selectMultiple}">
		$("#${input}").val(url);//</c:if>
		${input}Preview();
		//top.$.jBox.close();
	}
	function ${input}Callback(api){
		ckfinderAPI = api;
	}
	function ${input}Del(obj){
		var url = $(obj).prev().attr("url");
		$("#${input}").val($("#${input}").val().replace("|"+url,"","").replace(url+"|","","").replace(url,"",""));
		${input}Preview();
	}
	function ${input}DelAll(){
		$("#${input}").val("");
		${input}Preview();
	}
	function ${input}Preview(){
		var li, urls = $("#${input}").val().split("|");
		$("#${input}Preview").children().remove();
		for (var i=0; i<urls.length; i++){
			if (urls[i]!=""){//<c:if test="${type eq 'thumb' || type eq 'images'}">
				li = "<li><img src=\""+urls[i]+"\" url=\""+urls[i]+"\" style=\"max-width:200px;max-height:200px;_height:200px;border:0;padding:3px;\">";//</c:if><c:if test="${type ne 'thumb' && type ne 'images'}">
				li = "<li><a href=\""+urls[i]+"\" url=\""+urls[i]+"\" target=\"_blank\">"+decodeURIComponent(urls[i].substring(urls[i].lastIndexOf("/")+1))+"</a>";//</c:if>
				li += "&nbsp;&nbsp;<a href=\"javascript:\" onclick=\"${input}Del(this);\">×</a></li>";
				$("#${input}Preview").append(li);
			}
		}
	}
	${input}Preview();
</script>

 最主要的一个引入js的方法:在ckeditor.tag中调用

function include(id, path, file) {
    if (document.getElementById(id) == null) {
        var files = typeof file == "string" ? [ file ] : file;
        for ( var i = 0; i < files.length; i++) {
            var name = files[i].replace(/^\s|\s$/g, "");
            var att = name.split('.');
            var ext = att[att.length - 1].toLowerCase();
            var isCSS = ext == "css";
            var tag = isCSS ? "link" : "script";
            var attr = isCSS ? " type='text/css' rel='stylesheet' "
                    : " type='text/javascript' ";
            var link = (isCSS ? "href" : "src") + "='" + path + name + "'";
            document.write("<" + tag + (i == 0 ? " id=" + id : "") + attr
                    + link + "></" + tag + ">");
        }
    }
}

 2)在ckeditor  config中配置上传  ---基于ckfinder自身的上传

CKEDITOR.editorConfig = function( config ) {
	config.language = 'zh-cn'; 
	config.uiColor = '#f7f5f4';
	//config.skin="v2";
	config.width = '99.7%'; 
	config.height = '300px';
	config.removePlugins = 'elementspath,scayt';
	config.disableNativeSpellChecker = false;
	config.resize_dir = 'vertical';
	config.keystrokes =[[ CKEDITOR.CTRL + 13 /*Enter*/, 'maximize' ]];	
	config.extraPlugins = 'tableresize';
	config.enterMode = CKEDITOR.ENTER_P;
	config.shiftEnterMode = CKEDITOR.ENTER_BR;
	config.font_names='宋体/宋体;黑体/黑体;仿宋/仿宋_GB2312;楷体/楷体_GB2312;隶书/隶书;幼圆/幼圆;微软雅黑/微软雅黑;'+ config.font_names;
	config.image_previewText='&nbsp;';
	config.toolbar_default = [
		['Source'],
		['Cut','Copy','Paste','PasteText','PasteFromWord','Undo','Redo'],
		['Link','Unlink','Anchor'],
		['Image','Flash','Table','HorizontalRule','SpecialChar','Smiley'],
		['Maximize'],
		 '/',
		['Bold','Italic','Underline','Strike','RemoveFormat'],
		['NumberedList','BulletedList','-','Outdent','Indent','Blockquote'],
	    ['JustifyLeft','JustifyCenter','JustifyRight','JustifyBlock'],
	    ['Styles','Font','FontSize'],
	    ['TextColor','BGColor']
	]; 
	config.toolbar = 'default';
	if(config.ckfinderPath){
		config.filebrowserBrowseUrl = config.ckfinderPath+'/ckfinder.html?type=files';
		config.filebrowserImageBrowseUrl = config.ckfinderPath+'/ckfinder.html?type=images';
		config.filebrowserFlashBrowseUrl = config.ckfinderPath+'/ckfinder.html?type=flash';
		config.filebrowserUploadUrl = config.ckfinderPath+'/core/connector/java/connector.java?command=QuickUpload&type=files';
		config.filebrowserImageUploadUrl = config.ckfinderPath+'/core/connector/java/connector.java?command=QuickUpload&type=images';
		config.filebrowserFlashUploadUrl = config.ckfinderPath+'/core/connector/java/connector.java?command=QuickUpload&type=flash';
		config.filebrowserWindowWidth = '1000';
		config.filebrowserWindowHeight = '700';
	}
};
CKEDITOR.stylesSet.add( 'default', [
	/* Block Styles */
	{ name : '首行缩进'	, element : 'p', styles : { 'text-indent' : '20pt' } },
	/* Inline Styles */
	{ name : '标注黄色'	, element : 'span', styles : { 'background-color' : 'Yellow' } },
	{ name : '标注绿色'	, element : 'span', styles : { 'background-color' : 'Lime' } },
	/* Object Styles */
	{ name : '图片左对齐', element : 'img', attributes : { 'style' : 'padding: 5px; margin-right: 5px', 'border' : '2', 'align' : 'left' } },
	{ name : '图片有对齐', element : 'img', attributes : { 'style' : 'padding: 5px; margin-left: 5px', 'border' : '2', 'align' : 'right' } },
	{ name : '无边界表格', element : 'table', styles: { 'border-style': 'hidden', 'background-color' : '#E6E6FA' } }
]);

3)将ckfinder.xml放入WEB-INF目录下

4)在web.xml中配置ckfinder

<!-- CKFinder 编辑器可上传图片附件 -->
  	<servlet>
    	<servlet-name>CKFinderConnectorServlet</servlet-name>
    	<servlet-class>hs.ckeditor.CKFinderConnectorServlet</servlet-class>
    	<init-param>
      		<param-name>XMLConfig</param-name>
      		<param-value>/WEB-INF/ckfinder.xml</param-value>
    	</init-param>
    	<init-param>
      		<param-name>debug</param-name>
      		<param-value>false</param-value>
    	</init-param>
    	<init-param>
      		<param-name>configuration</param-name>
      		<param-value>hs.ckeditor.CKFinderConfig</param-value>
    	</init-param>
    	<load-on-startup>1</load-on-startup>
  	</servlet>
  	<servlet-mapping>
    	<servlet-name>CKFinderConnectorServlet</servlet-name>
    	<url-pattern>/scripts/ckfinder/core/connector/java/connector.java</url-pattern>
  	</servlet-mapping>
  	<filter>
    	<filter-name>FileUploadFilter</filter-name>
    	<filter-class>com.ckfinder.connector.FileUploadFilter</filter-class>
    	<init-param>
      		<param-name>sessionCookieName</param-name>
      		<param-value>JSESSIONID</param-value>
    	</init-param>
    	<init-param>
      		<param-name>sessionParameterName</param-name>
      		<param-value>jsessionid</param-value>
    	</init-param>
  	</filter>
  	<filter-mapping>
    	<filter-name>FileUploadFilter</filter-name>
    	<url-pattern>/scripts/ckfinder/core/connector/java/connector.java</url-pattern>
  	</filter-mapping>

 其中hs.ckeditor.CKFinderConfig 需要自己定义。

CKFinderConfig.java

import javax.servlet.ServletConfig;
import javax.servlet.http.HttpServletRequest;

import com.ckfinder.connector.ServletContextFactory;
import com.ckfinder.connector.configuration.Configuration;
import com.ckfinder.connector.utils.AccessControlUtil;

/**
 * CKFinder配置
 * @author selina
 * @version 2013-08-06
 */
public class CKFinderConfig extends Configuration {

	public CKFinderConfig(ServletConfig servletConfig) {
        super(servletConfig);  
    }
	
	@Override
    protected Configuration createConfigurationInstance() {
		AccessControlUtil.getInstance(this).loadACLConfig();
		try {
			this.baseURL = ServletContextFactory.getServletContext().getContextPath()+"/userfiles/"
					+"/";
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		return new CKFinderConfig(this.servletConf);
    }

    @Override  
    public boolean checkAuthentication(final HttpServletRequest request) {
    	//权限验证  
    	return true;
    }

}

 CKFinderConnectorServlet.java

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.ckfinder.connector.ConnectorServlet;

/**
 * CKFinderConnectorServlet
 * @author selina
 * @version 2013-08-06
 */
public class CKFinderConnectorServlet extends ConnectorServlet {
	
	private static final long serialVersionUID = 1L;
	
	@Override
	protected void doGet(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		prepareGetResponse(request, response, false);
		super.doGet(request, response);
	}
	
	@Override
	protected void doPost(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		prepareGetResponse(request, response, true);
		super.doPost(request, response);
	}
	
	private void prepareGetResponse(final HttpServletRequest request,
			final HttpServletResponse response, final boolean post) throws ServletException {
		String command = request.getParameter("command");
		String type = request.getParameter("type");
		// 初始化时,如果startupPath文件夹不存在,则自动创建startupPath文件夹
		if ("Init".equals(command)){
				String startupPath = request.getParameter("startupPath");// 当前文件夹可指定为模块名
				if (startupPath!=null){
					String[] ss = startupPath.split(":");
					if (ss.length==2){
						String path = "/userfiles/"+ss[0]+ss[1];
						String realPath = request.getSession().getServletContext().getRealPath(path);
						FileUtils.createDirectory(realPath);
					}
				}
		}
		// 快捷上传,自动创建当前文件夹,并上传到该路径
		else if ("QuickUpload".equals(command) && type!=null){
				String currentFolder = request.getParameter("currentFolder");// 当前文件夹可指定为模块名
				String path = "/userfiles/"+type+(currentFolder!=null?currentFolder:"");
				String realPath = request.getSession().getServletContext().getRealPath(path);
				FileUtils.createDirectory(realPath);
		}
//		System.out.println("------------------------");
//		for (Object key : request.getParameterMap().keySet()){
//			System.out.println(key + ": " + request.getParameter(key.toString()));
//		}
	}
	
}

 

总的来说就是这些了。

 

 

 

 

总结:通过结合ckeditor与ckfinder可实现编辑器文件上传并且还提供文件夹供浏览,不过这样设置会把文件等保存在项目内,如果文件过多,就会导致资源过多且不易安装与维护。

其实呢,ckfinder也是比较强大的,通过配置ckfinder.xml中的BaseDir也可以实现把文件保存在项目外的功能。不过要在tomcat配置虚拟路径。说明如下:

#当ckfinder.xml中配置了baseDir路径时,附件保存在项目外。不配置时默认在项目内。
当ckfinder.xml配置如下时:
<baseDir>d:/xxAttacm/userfiles/</baseDir>
<baseURL>/userfiles/</baseURL>
必须在tomcat server.xml下建立虚拟路径如下:
在<Host></Host>之间加入<Context docBase="d:\xxAttacm\userfiles\" path="/myProject/userfiles" reloadable="true"/>
其中myProject为项目发布根目录。docBase需与baseDir对应。

 

 

 

因该文章过长,为不影响浏览效果,第二种方式《CKEditor文件上传-多种方式-自定义上传-保存在项目外

将在后续补上。如有不足,欢迎指正!

 

 

分享到:
评论
1 楼 hui963966800 2017-04-12  
如何在上传完图片生成的<img>标签中把项目的域名也拼接上

相关推荐

Global site tag (gtag.js) - Google Analytics