关于如何建立两个ftp连接传输文件以及其中踩坑记录


1.创建一个连接FTP的工具类FTPUtil.java

package com.metarnet.ftp.util;

import java.io.IOException;
import java.io.InputStream;
import java.net.SocketException;
import java.util.Properties;

import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPReply;
import org.apache.log4j.Logger;

public class FTPUtil {
private static Logger logger = Logger.getLogger(FTPUtil.class);



/**
* 获取FTPClient对象
* @param ftpHost FTP主机服务器
* @param ftpPassword FTP 登录密码
* @param ftpUserName FTP登录用户名
* @param ftpPort FTP端口 默认为21
* @return
*/
public static FTPClient getFTPClient(String ftpHost, String ftpPassword,
String ftpUserName, int ftpPort) {
FTPClient ftpClient = null;
try {
ftpClient = new FTPClient();

ftpClient .setControlEncoding("UTF-8");//这里一定要设置字符编码,不然无法读取中文路径
ftpClient.connect(ftpHost, ftpPort);// 连接FTP服务器
ftpClient.login(ftpUserName, ftpPassword);// 登陆FTP服务器
if (!FTPReply.isPositiveCompletion(ftpClient.getReplyCode())) {
logger.info("未连接到FTP,用户名或密码错误。");
ftpClient.disconnect();
} else {
logger.info("FTP连接成功。");
}
} catch (SocketException e) {
e.printStackTrace();
logger.info("FTP的IP地址可能错误,请正确配置。");
} catch (IOException e) {
e.printStackTrace();
logger.info("FTP的端口错误,请正确配置。");
}
return ftpClient;
}
}

2.创建两个ftp链接

FTPClient ftpClient1 = getFTPClient(host1,port1,account1,password1);//源ftp

FTPClient ftpClient2 = getFTPClient(host2,port2,account2,password2);//目标ftp

boolean b1 = ftpClient1.changeWorkingDirectory("源ftp文件目录")//使用changeWorkingDirectory切换到指定目录

if(!b1){ //如果b1为false ,说明找不到源ftp文件目录,就别执行传输了

  ftpClient2.disconnect();

  ftpClient1.disconnect();

boolean b2 = ftpClient2.changeWorkingDirectory("目标ftp文件目录")//使用changeWorkingDirectory切换到指定目录

if(!b2){ // 如果b2为false ,说明找不到目标ftp文件目录,可以创建这个目录

  //坑1:ftp创建多级目录必须要循环创建,不然创建不成功而且不会报错

  ftpClient2.makeDirectory("目标ftp文件目录");

  b2 = makeDir(ftpClient2,"目标ftp文件目录");

InputStream inputstream1 = ftpClient1.retrieveFileSteam("文件名");//根据文件名获取源ftp文件输入流

//坑2:inputstream1.available();每次获取的文件大小不同,不清楚什么原因

if(inputstream1  != null && b2){

  //开始copy文件

  //坑3:不要在这之前执行ftpClient2.retrieveFileSteam("文件名");//可能你会用这个方法判断目标路径是否已经存在文件(如果存在可以不用再重复传输),但是这样操作后再执行下面的会一直为false             

  ftpClient2.storeFile方法 copySucceed                                 

  boolean copySucceed = ftpClient2.storeFile("文件名",inputstream1);

  if(!copySucceed){

    copySucceed = ftpClient2.storeFile(new String("文件名".getBytes(”uft-8“),"iso-8859-1"),inputstream1);

boolean makeDir(FTPClient ftp,string path) throws IOEception{

  // 分割
  String[] paths = path.split("/");
  // 创建成功标识
  boolean isMakeSucess = false;
  // 遍历每一级路径
  for (String str : paths) {
  // 切换目录,根据切换是否成功判断子目录是否存在
  boolean changeSuccess = ftp.changeWorkingDirectory(str);
  // 该级路径不存在就创建并切换
  if (!changeSuccess) {
  isMakeSucess = ftp.makeDirectory(str);
  ftp.changeWorkingDirectory(str);
}
}
return isMakeSucess;