UEDITOR FTP上传




原作者地址:点击打开链接


以下为复制(其中我修改了某些地方标红):


最近在项目中遇到了使用文本编辑器的情况,但是根据项目要求,文本编辑器的图片不能保存在本地服务器上,必须


上传到远程文件服务器上,找了众多资料,没有找到答案,最后终于自己反编译了百度的JAR包,完完整整的研究了一


次逻辑,终于实现了该功能,这里分享一下.以免后来者枉费时间.


步骤1.在自己的工程中实现一个ActionEnter类

package com.xxxx.ueditor;


import com.baidu.ueditor.ConfigManager;
import com.baidu.ueditor.define.ActionMap;
import com.baidu.ueditor.define.BaseState;
import com.baidu.ueditor.define.State;
import com.baidu.ueditor.hunter.FileManager;
import com.baidu.ueditor.hunter.ImageHunter;
import com.xxxx.ueditor.upload.Uploader;


import java.util.Map;


import javax.servlet.http.HttpServletRequest;


import org.apache.log4j.Logger;


public class ActionEnter
{
  //日志器
  protected Logger log = Logger.getLogger(ActionEnter.class);
                
  private HttpServletRequest request = null;


  private String rootPath = null;
  private String contextPath = null;


  private String actionType = null;


  private ConfigManager configManager = null;


  public ActionEnter(HttpServletRequest request, String rootPath)
  {
    this.request = request;
    this.rootPath = rootPath;
    this.actionType = request.getParameter("action");
    this.contextPath = request.getContextPath();
    this.configManager = ConfigManager.getInstance(this.rootPath, this.contextPath, 


request.getRequestURI());
  }


  public String exec()
  {
    String callbackName = this.request.getParameter("callback");


    if (callbackName != null)
    {
      if (!validCallbackName(callbackName)) {
        return new BaseState(false, 401).toJSONString();
      }


      return callbackName + "(" + invoke() + ");";
    }


    String response = invoke();
    log.debug(response);
    return response;
  }


  @SuppressWarnings({ "unchecked", "rawtypes" })
public String invoke()
  {
    if ((this.actionType == null) || (!ActionMap.mapping.containsKey(this.actionType))) {
      return new BaseState(false, 101).toJSONString();
    }


    if ((this.configManager == null) || (!this.configManager.valid())) {
      return new BaseState(false, 102).toJSONString();
    }


    State state = null;


    int actionCode = ActionMap.getType(this.actionType);


    Map conf = null;


    switch (actionCode)
    {
    case 0:
      return this.configManager.getAllConfig().toString();
    case 1:
    case 2:
    case 3:
    case 4:
      conf = this.configManager.getConfig(actionCode);
      conf.put("useFtpUpload",this.configManager.getAllConfig().getString("useFtpUpload"));
      conf.put("keepLocalFile",this.configManager.getAllConfig().getString("keepLocalFile"));
      state = new Uploader(this.request, conf).doExec();
      break;
    case 5:
      conf = this.configManager.getConfig(actionCode);
      String[] list = this.request.getParameterValues((String)conf.get("fieldName"));
      state = new ImageHunter(conf).capture(list);
      break;
    case 6:
    case 7:
      conf = this.configManager.getConfig(actionCode);
      int start = getStartIndex();
      state = new FileManager(conf).listFile(start);
    }


    return state.toJSONString();
  }


  public int getStartIndex()
  {
    String start = this.request.getParameter("start");
    try
    {
      return Integer.parseInt(start); } catch (Exception e) {
    }
    return 0;
  }


  public boolean validCallbackName(String name)
  {
    if (name.matches("^[a-zA-Z_]+[\\w0-9_]*$")) {
      return true;
    }


    return false;
  }
}

这个类是反编译的原有百度的代码,只加入了两行读取配置文件的内容:


conf.put("useFtpUpload",this.configManager.getAllConfig().getString("useFtpUpload"));   //是否使用

FTP上传
conf.put("keepLocalFile",this.configManager.getAllConfig().getString("keepLocalFile")); //是否上传



后保留本地服务器文件


步骤2.在ueditor目录下的jsp目录下,找到controller.jsp,修改ActionEnter的实现

<%@ page language="java" contentType="text/html; charset=UTF-8" 


import="com.xxxx.ueditor.ActionEnter"
    pageEncoding="UTF-8"%>
<%


    request.setCharacterEncoding( "utf-8" );
    response.setHeader("Content-Type" , "text/html");
    
    String rootPath = application.getRealPath( "/" );
    
    out.write( new ActionEnter( request, rootPath ).exec() );
    
%>

只修改一处import改为刚才创建的ActionEnter即可


步骤3.修改controller.jsp同级目录下的config.json,加入之前新增的两个配置项,并且修改prefix为文件服务器的域名

/* 前后端通信相关的配置,注释只允许使用多行方式 */
{
    "useFtpUpload": "true", /* 是否使用FTP上传 */
    "keepLocalFile": "true", /* 使用FTP上传后本地服务器是否保存 */
    
    /* 上传图片配置项 */
    "imageActionName": "uploadimage", /* 执行上传图片的action名称 */
    "imageFieldName": "upfile", /* 提交的图片表单名称 */
    "imageMaxSize": 3145728, /* 上传大小限制,单位B */
    "imageAllowFiles": [".png", ".jpg", ".jpeg", ".gif", ".bmp"], /* 上传图片格式显示 */
    "imageCompressEnable": true, /* 是否压缩图片,默认是true */
    "imageCompressBorder": 1600, /* 图片压缩最长边限制 */
    "imageInsertAlign": "none", /* 插入的图片浮动方式 */
    "imageUrlPrefix": "http://localhost:8081/", /* 图片访问路径前缀 */
    "imagePathFormat": "/upload/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保


存路径和文件名格式 */
                                /* {filename} 会替换成原文件名,配置这项需要注意中文乱码问题 */
                                /* {rand:6} 会替换成随机数,后面的数字是随机数的位数 */
                                /* {time} 会替换成时间戳 */
                                /* {yyyy} 会替换成四位年份 */
                                /* {yy} 会替换成两位年份 */
                                /* {mm} 会替换成两位月份 */
                                /* {dd} 会替换成两位日期 */
                                /* {hh} 会替换成两位小时 */
                                /* {ii} 会替换成两位分钟 */
                                /* {ss} 会替换成两位秒 */
                                /* 非法字符 \ : * ? " < > | */
                                /* 具请体看线上文档: fex.baidu.com/ueditor/#use-


format_upload_filename */


    /* 涂鸦图片上传配置项 */
    "scrawlActionName": "uploadscrawl", /* 执行上传涂鸦的action名称 */
    "scrawlFieldName": "upfile", /* 提交的图片表单名称 */
    "scrawlPathFormat": "/upload/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保


存路径和文件名格式 */
    "scrawlMaxSize": 2048000, /* 上传大小限制,单位B */
    "scrawlUrlPrefix": "", /* 图片访问路径前缀 */
    "scrawlInsertAlign": "none",


    /* 截图工具上传 */
    "snapscreenActionName": "uploadimage", /* 执行上传截图的action名称 */
    "snapscreenPathFormat": "/upload/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定


义保存路径和文件名格式 */
    "snapscreenUrlPrefix": "", /* 图片访问路径前缀 */
    "snapscreenInsertAlign": "none", /* 插入的图片浮动方式 */


    /* 抓取远程图片配置 */
    "catcherLocalDomain": ["127.0.0.1", "localhost", "img.baidu.com"],
    "catcherActionName": "catchimage", /* 执行抓取远程图片的action名称 */
    "catcherFieldName": "source", /* 提交的图片列表表单名称 */
    "catcherPathFormat": "/upload/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义


保存路径和文件名格式 */
    "catcherUrlPrefix": "", /* 图片访问路径前缀 */
    "catcherMaxSize": 2048000, /* 上传大小限制,单位B */
    "catcherAllowFiles": [".png", ".jpg", ".jpeg", ".gif", ".bmp"], /* 抓取图片格式显示 */


    /* 上传视频配置 */
    "videoActionName": "uploadvideo", /* 执行上传视频的action名称 */
    "videoFieldName": "upfile", /* 提交的视频表单名称 */
    "videoPathFormat": "/upload/video/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保


存路径和文件名格式 */
    "videoUrlPrefix": "http://localhost:8081/", /* 视频访问路径前缀 */
    "videoMaxSize": 102400000, /* 上传大小限制,单位B,默认100MB */
    "videoAllowFiles": [
        ".flv", ".swf", ".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg",
        ".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav", ".mid"], /* 上传视频格式显


示 */


    /* 上传文件配置 */
    "fileActionName": "uploadfile", /* controller里,执行上传视频的action名称 */
    "fileFieldName": "upfile", /* 提交的文件表单名称 */
    "filePathFormat": "/upload/file/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存


路径和文件名格式 */
    "fileUrlPrefix": "http://localhost:8081/", /* 文件访问路径前缀 */
    "fileMaxSize": 51200000, /* 上传大小限制,单位B,默认50MB */
    "fileAllowFiles": [
        ".png", ".jpg", ".jpeg", ".gif", ".bmp",
        ".flv", ".swf", ".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg",
        ".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav", ".mid",
        ".rar", ".zip", ".tar", ".gz", ".7z", ".bz2", ".cab", ".iso",
        ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".pdf", ".txt", ".md", ".xml"
    ], /* 上传文件格式显示 */


    /* 列出指定目录下的图片 */
    "imageManagerActionName": "listimage", /* 执行图片管理的action名称 */
    "imageManagerListPath": "/upload/image/", /* 指定要列出图片的目录 */
    "imageManagerListSize": 20, /* 每次列出文件数量 */
    "imageManagerUrlPrefix": "http://localhost:8081/", /* 图片访问路径前缀 */
    "imageManagerInsertAlign": "none", /* 插入的图片浮动方式 */
    "imageManagerAllowFiles": [".png", ".jpg", ".jpeg", ".gif", ".bmp"], /* 列出的文件类型 */


    /* 列出指定目录下的文件 */
    "fileManagerActionName": "listfile", /* 执行文件管理的action名称 */
    "fileManagerListPath": "/upload/file/", /* 指定要列出文件的目录 */
    "fileManagerUrlPrefix": "http://localhost:8081/", /* 文件访问路径前缀 */
    "fileManagerListSize": 20, /* 每次列出文件数量 */
    "fileManagerAllowFiles": [
        ".png", ".jpg", ".jpeg", ".gif", ".bmp",
        ".flv", ".swf", ".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg",
        ".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav", ".mid",
        ".rar", ".zip", ".tar", ".gz", ".7z", ".bz2", ".cab", ".iso",
        ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".pdf", ".txt", ".md", ".xml"
    ] /* 列出的文件类型 */


}

步骤4.创建一个Uploader类,其他代码反编译百度,加入红色内容,通过配置文件配置是上传本地服务器还是远程FTP服务器

package com.xxxx.ueditor.upload;


import com.baidu.ueditor.define.State;
import com.baidu.ueditor.upload.Base64Uploader;
import com.baidu.ueditor.upload.BinaryUploader;


import java.util.Map;


import javax.servlet.http.HttpServletRequest;


public class Uploader {
    
      private HttpServletRequest request = null;
      private Map<String, Object> conf = null;


      public Uploader(HttpServletRequest request, Map<String, Object> conf) {
        this.request = request;
        this.conf = conf;
      }


      public final State doExec() {
        String filedName = (String)this.conf.get("fieldName");
        State state = null;


        //保留原有逻辑,在json.config中加入是否使用FTP上传配置项
        if ("true".equals(this.conf.get("isBase64")))
          state = Base64Uploader.save(this.request.getParameter(filedName), 
            this.conf);
        else {
          if("true".equals(this.conf.get("useFtpUpload")))
              state = FtpUploader.save(request, conf);
          else
            state = BinaryUploader.save(this.request, this.conf);
        }


        return state;
      }
}


步骤5.创建一个FtpUploader类,内容是反编译的BinaryUploader,稍作修改,保证在远程服务器上创建路径和本地服务器的一致

package com.xxxx.ueditor.upload;


import com.baidu.ueditor.PathFormat;
import com.baidu.ueditor.define.BaseState;
import com.baidu.ueditor.define.FileType;
import com.baidu.ueditor.define.State;


import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.List;
import java.util.Map;


import javax.servlet.http.HttpServletRequest;


import org.apache.commons.fileupload.FileItemIterator;
import org.apache.commons.fileupload.FileItemStream;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;


public class FtpUploader
{
    
  public static final State save(HttpServletRequest request, Map<String, Object> conf)
  {
    FileItemStream fileStream = null;
    boolean isAjaxUpload = request.getHeader("X_Requested_With") != null;


    if (!ServletFileUpload.isMultipartContent(request)) {
      return new BaseState(false, 5);
    }


    ServletFileUpload upload = new ServletFileUpload(
      new DiskFileItemFactory());


    if (isAjaxUpload) {
      upload.setHeaderEncoding("UTF-8");
    }
    try
    {
      FileItemIterator iterator = upload.getItemIterator(request);


      while (iterator.hasNext()) {
        fileStream = iterator.next();


        if (!fileStream.isFormField())
          break;
        fileStream = null;
      }


      if (fileStream == null) {
        return new BaseState(false, 7);
      }


      String savePath = (String)conf.get("savePath");
      String originFileName = fileStream.getName();
      String suffix = FileType.getSuffixByFilename(originFileName);


      originFileName = originFileName.substring(0, 
        originFileName.length() - suffix.length());
      savePath = savePath + suffix;


      long maxSize = ((Long)conf.get("maxSize")).longValue();


      if (!validType(suffix, (String[])conf.get("allowFiles"))) {
        return new BaseState(false, 8);
      }


      savePath = PathFormat.parse(savePath, originFileName);
      
      String remoteDir = "";
      
      int pos = savePath.lastIndexOf("/");
      if(pos > -1){
          remoteDir = savePath.substring(0,pos + 1);
      }


      String physicalPath = (String)conf.get("rootPath") + savePath;


      boolean keepLocalFile = "false".equals(conf.get("keepLocalFile")) ? false : true;
      InputStream is = fileStream.openStream();
      State storageState = StorageManager.saveFtpFileByInputStream(is, remoteDir,
        physicalPath, maxSize, keepLocalFile);
      is.close();


      if (storageState.isSuccess()) {
      <span style="color:#ff0000;">  //storageState.putInfo("url", savePath);这里返回地址为了返回的是,ftp服务器上的地址,所以这里注释掉</span>
        storageState.putInfo("type", suffix);
        storageState.putInfo("original", originFileName + suffix);
      }


      return storageState;
    } catch (FileUploadException e) {
      return new BaseState(false, 6);
    } catch (IOException localIOException) {
    }
    return new BaseState(false, 4);
  }


  @SuppressWarnings("rawtypes")
private static boolean validType(String type, String[] allowTypes) {
    List list = Arrays.asList(allowTypes);


    return list.contains(type);
  }
}


步骤6.创建一个StorageManager类,内容反编译百度原有内容,加入几个FTP相关函数


package com.witontek.mobilehospital.ueditor;

import com.baidu.ueditor.define.BaseState;
import com.baidu.ueditor.define.State;


import com.witontek.mobilehospital.tools.FileUtil;
import com.witontek.mobilehospital.tools.config.CommProperties;
import com.witontek.mobilehospital.tools.random.UUIDGenerator;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

import org.apache.commons.io.FileUtils;

public class StorageManager
{
    
  public static final int BUFFER_SIZE = 8192;

  public static State saveBinaryFile(byte[] data, String path)
  {
    File file = new File(path);

    State state = valid(file);

    if (!state.isSuccess()) {
      return state;
    }
    try
    {
      BufferedOutputStream bos = new BufferedOutputStream(
        new FileOutputStream(file));
      bos.write(data);
      bos.flush();
      bos.close();
    } catch (IOException ioe) {
      return new BaseState(false, 4);
    }

    state = new BaseState(true, file.getAbsolutePath());
    state.putInfo("size", data.length);
    state.putInfo("title", file.getName());
    return state;
  }

  public static State saveFileByInputStream(InputStream is, String path, long maxSize)
  {
    State state = null;

    File tmpFile = getTmpFile();

    byte[] dataBuf = new byte[2048];
    BufferedInputStream bis = new BufferedInputStream(is, 8192);
    try
    {
      BufferedOutputStream bos = new BufferedOutputStream(
        new FileOutputStream(tmpFile), 8192);

      int count = 0;
      while ((count = bis.read(dataBuf)) != -1) {
        bos.write(dataBuf, 0, count);
      }
      bos.flush();
      bos.close();

      if (tmpFile.length() > maxSize) {
        tmpFile.delete();
        return new BaseState(false, 1);
      }

      state = saveTmpFile(tmpFile, path);

      if (!state.isSuccess()) {
        tmpFile.delete();
      }

      return state;
    }
    catch (IOException localIOException) {
    }
    return new BaseState(false, 4);
  }

  public static State saveFileByInputStream(InputStream is, String path) {
    State state = null;

    File tmpFile = getTmpFile();

    byte[] dataBuf = new byte[2048];
    BufferedInputStream bis = new BufferedInputStream(is, 8192);
    try
    {
      BufferedOutputStream bos = new BufferedOutputStream(
        new FileOutputStream(tmpFile), 8192);

      int count = 0;
      while ((count = bis.read(dataBuf)) != -1) {
        bos.write(dataBuf, 0, count);
      }
      bos.flush();
      bos.close();

      state = saveTmpFile(tmpFile, path);

      if (!state.isSuccess()) {
        tmpFile.delete();
      }

      return state;
    } catch (IOException localIOException) {
    }
    return new BaseState(false, 4);
  }

  private static File getTmpFile() {
    File tmpDir = FileUtils.getTempDirectory();
    double d = Math.random() * 10000.0D;
    String tmpFileName = String.valueOf(d).replace(".", "");
    return new File(tmpDir, tmpFileName);
  }

  private static State saveTmpFile(File tmpFile, String path) {
    State state = null;
    File targetFile = new File(path);

    if (targetFile.canWrite())
      return new BaseState(false, 2);
    try
    {
      FileUtils.moveFile(tmpFile, targetFile);
    } catch (IOException e) {
      return new BaseState(false, 4);
    }

    state = new BaseState(true);
    state.putInfo("size", targetFile.length());
    state.putInfo("title", targetFile.getName());

    return state;
  }

  private static State valid(File file) {
    File parentPath = file.getParentFile();

    if ((!parentPath.exists()) && (!parentPath.mkdirs())) {
      return new BaseState(false, 3);
    }

    if (!parentPath.canWrite()) {
      return new BaseState(false, 2);
    }

    return new BaseState(true);
  }
  
  /**
   * 上传FTP文件
   * @param is
   * @param path
   * @param maxSize
   * @return
   */
  public static State saveFtpFileByInputStream(InputStream is, String remoteDir, String path, long maxSize,boolean keepLocalFile)
  {
    State state = null;

    File tmpFile = getTmpFile();

    byte[] dataBuf = new byte[2048];
    BufferedInputStream bis = new BufferedInputStream(is, 8192);
    try
    {
      BufferedOutputStream bos = new BufferedOutputStream(
        new FileOutputStream(tmpFile), 8192);

      int count = 0;
      while ((count = bis.read(dataBuf)) != -1) {
        bos.write(dataBuf, 0, count);
      }
      bos.flush();
      bos.close();

      if (tmpFile.length() > maxSize) {
        tmpFile.delete();
        return new BaseState(false, 1);
      }

      state = saveFtpTmpFile(tmpFile, remoteDir, path, keepLocalFile);

      if (!state.isSuccess()) {
        tmpFile.delete();
      }

      return state;
    }
    catch (IOException localIOException) {
    }
    return new BaseState(false, 4);
  }
  private static String picturePath = CommProperties.getProp("NEWS")+"/picture/";
  
  private static State saveFtpTmpFile(File tmpFile, String remoteDir, String path,boolean keepLocalFile) {
        State state = null;
        File targetFile = new File(path);

        if (targetFile.canWrite())
          return new BaseState(false, 2);
        try
        {
          FileUtils.moveFile(tmpFile, targetFile);
        } catch (IOException e) {
          return new BaseState(false, 4);
        }<span style="color:#ff0000;">//这里增加自己的上传到ftp服务器的代码</span>
       <span style="color:#ff0000;"> double d = Math.random();
        String fileName = UUIDGenerator.getUUID()+ d + ".jpg";
        String ftpPath ;
        try
        {
        	 File file = targetFile;
              if (file != null) {
                 FileUtil.ftpUpload(file,  fileName, "/news/ueditor");
             }
              ftpPath = picturePath + "ueditor/" + fileName;
         }catch (Exception e) {
            return new BaseState(false, 4);
        }</span>
        
        try
        {
            if(! keepLocalFile)
                targetFile.delete();
        }catch(Exception e){
            
        }

        state = new BaseState(true);
        state.putInfo("size", targetFile.length());
        state.putInfo("title",fileName);
        <span style="color:#ff0000;">state.putInfo("url", ftpPath);//这里返回的是ftp服务器地址</span>

        return state;
  }
}

7.ftpUpload 上传到ftp服务器的代码

<span style="color:#ff0000;">/***
	 * ftp图片上传
	 * 
	 * @param srcFile文件流
	 * @param destFileName上传后文件名
	 * @param destFoldName上传后文件包名
	 */
	public static void ftpUpload(File srcFile, String fileName, String foldName) {
		FTPClient ftpClient = new FTPClient();
		FileInputStream fis = null;

		try {

			ftpClient.connect(server);
			ftpClient.login(uname, pwd);

			fis = new FileInputStream(srcFile);
			// 设置上传目录
			ftpClient.changeWorkingDirectory(foldName);
			ftpClient.setBufferSize(1024);
			ftpClient.enterLocalPassiveMode();
			if (FTPReply.isPositiveCompletion(ftpClient.sendCommand("OPTS UTF8", "ON"))) {
		       // 开启服务器对UTF-8的支持,如果服务器支持就用UTF-8编码,否则就使用本地编码(GBK).
		       LOCAL_CHARSET = "UTF-8";
			}
			ftpClient.setControlEncoding(LOCAL_CHARSET);
			fileName = new String(fileName.getBytes(LOCAL_CHARSET),SERVER_CHARSET);
			// 设置文件类型(二进制)
			ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
			ftpClient.storeFile(fileName, fis);
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				ftpClient.disconnect();
			} catch (IOException e) {
				e.printStackTrace();
				throw new RuntimeException("关闭FTP连接发生异常!", e);
			}
		}
	}</span>

到此就完成了UEditor上传FTP服务器的工作了.

你可能感兴趣的:(java,ftp,服务器,ueditor)