Struts2,Webwork2关于使用FCKeditor,richtexteditor 的解决方法

傅鸿波
2023-12-01

一 Webwork2 + FCkeditor

 

这个问题由来已久,这里我有一个比较好的办法,和大家分享一下。

Webwork 测试版本为2.2.6  +  WinXP

配置好 Webwork 环境后,在你的项目里建一个类,内容如下:

 

/*
 * Copyright (c) 2002-2003 by OpenSymphony
 * All rights reserved.
 */
package com.leo.controller;

import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import javax.servlet.ServletContext;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.opensymphony.webwork.WebWorkException;
import com.opensymphony.webwork.components.AbstractRichtexteditorConnector;
import com.opensymphony.webwork.components.DefaultRichtexteditorConnector;
import com.opensymphony.webwork.util.ServletContextAware;
import com.opensymphony.webwork.views.util.UrlHelper;
import com.opensymphony.xwork.ActionContext;

/**
 * 
 * @author tm_jee
 * @version $Date: 2007-03-29 08:02:59 +0200 (Do, 29 Mrz 2007) $ $Id: DefaultRichtexteditorConnector.java 2883 2007-03-29 06:02:59Z tm_jee $
 */
public class MyConnector extends AbstractRichtexteditorConnector implements ServletContextAware {

    private static final Log _log = LogFactory.getLog(DefaultRichtexteditorConnector.class);

    private static final long serialVersionUID = -3792445192115623052L;

    protected String _actualServerPath = "/user_file/";
    protected String _serverPath = "/user_file/";


	public String getActualServerPath() { return _actualServerPath; }
    public void setActualServerPath(String actualServerPath) { _actualServerPath = actualServerPath; }


    protected String calculateServerPath(String serverPath, String folderPath, String type) throws Exception {
        //return UrlHelper.buildUrl(serverPath, _request, _response, null, _request.getScheme(), true, true, true);
        return UrlHelper.buildUrl(serverPath+type+folderPath, _request, _response, new HashMap(), _request.getScheme(), true, true, true);
    }

    protected String calculateActualServerPath(String actualServerPath, String type, String folderPath) throws Exception {
        String path = "file:"+servletContext.getRealPath(actualServerPath);
        path = path.trim();
        path = path.replace('\\', '/'); 
        makeDirIfNotExists(path);
        path = path.endsWith("/") ? path : path+"/";
        return path+type+folderPath;
    }

    private ServletContext servletContext;
    public void setServletContext(ServletContext servletContext) {
        this.servletContext = servletContext;
    }

    protected Folder[] getFolders(String virtualFolderPath, String type) throws Exception {
        String path = calculateActualServerPath(getActualServerPath(), type, virtualFolderPath);
        makeDirIfNotExists(path);
        java.io.File f = new java.io.File(new URI(path));
        java.io.File[] children = f.listFiles(new FileFilter() {
            public boolean accept(java.io.File pathname) {
                if (! pathname.isFile()) {
                    return true;
                }
                return false;
            }
        });

        List tmpFolders = new ArrayList();
        for (int a=0; a< children.length; a++) {
            tmpFolders.add(new Folder(children[a].getName()));
        }

        return (Folder[]) tmpFolders.toArray(new Folder[0]);
    }

    protected FoldersAndFiles getFoldersAndFiles(String virtualFolderPath, String type) throws Exception {
        String path = calculateActualServerPath(getActualServerPath(), type, virtualFolderPath);
        makeDirIfNotExists(path);
        java.io.File f = new java.io.File(new URI(path));
        java.io.File[] children = f.listFiles();

        List directories = new ArrayList();
        List files = new ArrayList();
        for (int a=0; a< children.length; a++) {
            if (children[a].isDirectory()) {
                directories.add(new Folder(children[a].getName()));
            }
            else {
                try {
                    files.add(new File(children[a].getName(), fileSizeInKBytes(children[a])));
                }
                catch(Exception e) {
                    _log.error("cannot deal with file "+children[a], e);
                }
            }
        }
        
        // TODO 非常重要的一句话,这样才能使用自定义的路径。
        ActionContext.getContext().put("__richtexteditorServerPath", calculateServerPath(get_serverPath(), getCurrentFolder(), getType()));

        return new FoldersAndFiles(
                (Folder[]) directories.toArray(new Folder[0]),
                (File[]) files.toArray(new File[0])
        );
    }

    protected CreateFolderResult createFolder(String virtualFolderPath, String type, String newFolderName) {
        try {
            String tmpPath = calculateActualServerPath(getActualServerPath(), type, virtualFolderPath);
            tmpPath = tmpPath+newFolderName;
            boolean alreadyExists = makeDirIfNotExists(tmpPath);
            if (alreadyExists) {
                return CreateFolderResult.folderAlreadyExists();
            }
        }
        catch(Exception e) {
            _log.error(e.toString(), e);
            return CreateFolderResult.unknownError();
        }
        return CreateFolderResult.noErrors();
    }

    protected FileUploadResult fileUpload(String virtualFolderPath, String type, String filename, String contentType, java.io.File newFile) {
        try {
            String tmpDir = calculateActualServerPath(getActualServerPath(), type, virtualFolderPath);
            makeDirIfNotExists(tmpDir);
            String tmpFile = tmpDir+filename;
            if(makeFileIfNotExists(tmpFile)) {
                // already exists
                int a=0;
                String ext = String.valueOf(a);
                tmpFile = calculateActualServerPath(getActualServerPath(), type, virtualFolderPath)+filename+ext;
                while(makeFileIfNotExists(tmpFile)) {
                    a = a + 1;
                    ext = String.valueOf(a);
                    if (a > 100) {
                        return FileUploadResult.invalidFile();
                    }
                    tmpFile = calculateActualServerPath(getActualServerPath(), type, virtualFolderPath)+filename+ext;
                }
                copyFile(newFile, new java.io.File(new URI(tmpFile)));
                return FileUploadResult.uploadCompleteWithFilenamChanged(filename+ext);
            }
            else {
                copyFile(newFile, new java.io.File(new URI(tmpFile)));
                return FileUploadResult.uploadComplete();
            }
        }
        catch(Exception e) {
            _log.error(e.toString(), e);
            return FileUploadResult.invalidFile();
        }
    }

    protected void unknownCommand(String command, String virtualFolderPath, String type, String filename, String contentType, java.io.File newFile) {
        throw new WebWorkException("unknown command "+command);
    }





    /**
     *
     * @param path
     * @return true if file already exists, false otherwise.
     */
    protected boolean makeDirIfNotExists(String path) throws URISyntaxException {
        java.io.File dir = new java.io.File(new URI(path));
        if (! dir.exists()) {
        	if (_log.isDebugEnabled()) {
        		_log.debug("make directory "+dir);
        	}
            boolean ok = dir.mkdirs();
            if (! ok) {
                throw new WebWorkException("cannot make directory "+dir);
            }
            return false;
        }
        return true;
    }

    /**
     *
     * @param filePath
     * @return true if file already exists, false otherwise
     */
    protected boolean makeFileIfNotExists(String filePath) throws IOException, URISyntaxException {
        java.io.File f = new java.io.File(new URI(filePath));
        if (! f.exists()) {
        	if (_log.isDebugEnabled()) {
        		_log.debug("creating file "+filePath);
        	}
            boolean ok = f.createNewFile();
            if (! ok) {
                throw new WebWorkException("cannot create file "+filePath);
            }
            return false;
        }
        return true;
    }

    protected void copyFile(java.io.File from, java.io.File to) throws FileNotFoundException, IOException {
        FileInputStream fis = null;
        FileOutputStream fos = null;
        try {
        	if (_log.isDebugEnabled()) {
        		_log.debug("copy file from "+from+" to "+to);
        	}
            fis = new FileInputStream(from);
            fos = new FileOutputStream(to);
            int tmpByte = fis.read();
            while(tmpByte != -1) {
                fos.write(tmpByte);
                tmpByte = fis.read();
            }
            fos.flush();
        }
        finally {
            if (fis != null)
                fis.close();
            if (fos != null)
                fos.close();
        }
    }

    protected long fileSizeInKBytes(java.io.File file) throws FileNotFoundException, IOException {
        FileInputStream fis = null;
        long size = 0;
        try {
            fis = new FileInputStream(file);
            size = fis.getChannel().size();
        }
        finally {
            if (fis != null)
                fis.close();
        }
        if (size > 0) {
            size = (size / 100);
        }
        if (_log.isDebugEnabled()) {
        	_log.debug("size of file "+file+" is "+size+" kb");
        }
        return size;
    }
    
    
    
    public String get_serverPath() {
		return _serverPath;
	}
	public void set_serverPath(String path) {
		_serverPath = path;
	}
}

 

 

注意以下变量部分:

1.在MyConnector.java第 42行的变量_actualServerPath 默认为值: /WEB-INF/classes/com/opensymphony/webwork/static/richtexteditor/data/, 从源码 com.opensymphony.webwork.components.DefaultRichtexteditorConnector.java 的第 38

protected String _actualServerPath = "/com/opensymphony/webwork/static/richtexteditor/data/";

以及第 51

 
String path = "file:"+servletContext.getRealPath("/WEB-INF/classes"+actualServerPath);

 

 

可以得出。  

因此,我这里改成 /user_file 文件夹作为文件上传路径,你可以自由选择。

 

2.在MyConnector.java第 43行的变量_serverPath 表示的是上传完附件后,选择的路径,默认为: /webwork/richtexteditor/data/ 。 从源码 com.opensymphony.webwork.components.AbstractRichtexteditorConnector.java 的第 73 行:

 

protected String _serverPath = "/webwork/richtexteditor/data/";

 可以看到。 但 FCKEditor 使用时,会变成: http://IP地址 /项目 /webwork/richtexteditor/data/ . 记住,这里不会带端口号的,这也是唯一美中不足的地方,如果要修改,可能要改动很大了。

 

 因此,我这里改成也 /user_file 文件夹,为了可以在上传成功后, FCKEditor 能够选择上传成功的文件。

 

最后来到MyConnector.java 的第112行:

 

 
// TODO 非常重要的一句话,这样才能使用自定义的路径。
        ActionContext.getContext().put("__richtexteditorServerPath", calculateServerPath(get_serverPath(), getCurrentFolder(), getType()));

 

 

这里我详细说一下: MyConnector.java 继承自 AbstractRichtexteditorConnector.java ,在 AbstractRichtexteditorConnector.java 源码146行左右有这么一段:

 

else if ("CreateFolder".equals(getCommand())) {
			_log.debug("Command "+getCommand()+" detected \n\t type="+getType()+"\n\t folderPath="+getCurrentFolder()+"\n\t newFolderName="+getNewFolderName());
			
			ActionContext.getContext().put("__richtexteditorCommand", getCommand());
			ActionContext.getContext().put("__richtexteditorType", getType());
			ActionContext.getContext().put("__richtexteditorFolderPath", getCurrentFolder());
			ActionContext.getContext().put("__richtexteditorServerPath", calculateServerPath(getServerPath(), getCurrentFolder(), getType()));
			
			CreateFolderResult createFolderResult = createFolder(getCurrentFolder(), getType(), getNewFolderName());
			
			ActionContext.getContext().put("__richtexteditorCreateFolder", createFolderResult);
			
			return CREATE_FOLDER;
		}
   在这段代码的第7行, 计算出的路径永远是父类里默认的 /webwork/richtexteditor/data/ 所以在它的子类 MyConnector.java ,我们重新赋值了一下:  
// TODO 非常重要的一句话,这样才能使用自定义的路径。
        ActionContext.getContext().put("__richtexteditorServerPath", calculateServerPath(get_serverPath(), getCurrentFolder(), getType()));

 

 

这样,就能保证我们刚才定义的 user_file 文件夹生效,文件通过 FCKEditor 上传完后,通过服务器端浏览,可以看到我们上传的图片,然后点确定就可以了。不过,如果你不是默认的 80 端口,那么可能要手动改一改,真是有点遗憾。最后一步,也是最重要的一步,配置我们刚才写的 MyConnector.java

 

<package name="richtexteditor-upload" extends="webwork-default"
		namespace="/webwork/richtexteditor/editor/filemanager/upload">
		<action name="uploader" class="com.leo.controller.MyConnector"
			method="upload">
			<result name="richtexteditorFileUpload" />
		</action>
	</package>

	<package name="richtexteditor-browse" extends="webwork-default"
		namespace="/webwork/richtexteditor/editor/filemanager/browser/default/connectors/jsp">
		<action name="connector" class="com.leo.controller.MyConnector"
			method="browse">
			<result name="getFolders" type="richtexteditorGetFolders" />
			<result name="getFoldersAndFiles"
				type="richtexteditorGetFoldersAndFiles" />
			<result name="createFolder"
				type="richtexteditorCreateFolder" />
			<result name="fileUpload" type="richtexteditorFileUpload" />
		</action>
	</package>

 

一切完成,直接在 JSP 里调用即可:
<ww:richtexteditor toolbarCanCollapse="true" width="700" label=""
					name="txt" value="可以正常上传了。" />

 

 

 

二 Struts2 + Dojo

 

Struts2 部分更简单了。虽然 Struts2 不直接支持 FCKeditor ,但直接 Dojo ,而且个人更喜欢这种简洁的风格,我用的是 Struts2.0.11 版本进行测试,使用时,只要配置两个地方

1. HTML<head /> 标签之间,加上

<s:head theme="ajax"/>

2. textarea 加上主题    
<s:textarea theme="ajax" />

 

就这么简单。

 

 

 

--------------------------------------------------------------------------------------

最近根据网上的文章,更新了一下这个版本。请下载webwork_fckeditor完美解决.rar

 

 

 类似资料: