public class FtpTool implements IFtpTool
{
/**
* 模块名
*/
private static final String[] KEY_WORD = new String[] {"FtpTool"};
/**
* 日志对象
*/
private static Log log = LogManager.getDebugLog();
private static final int NUM1000 = 1000;
private static final int DEFUALT_TIMEOUT_SECOND = 30;
/**
* ftp 默认端口
*/
private static final int FTP_DEFAULT_PORT = 21;
/**
* ftp服务端IP
*/
private String ftpServerIP;
/**
* ftp服务端端口
*/
private int ftpServerPort;
/**
* 服务端登陆用户名
*/
private String ftpUserName;
/**
* 服务端登陆密码
*/
private String ftpPassword;
/**
* 连接超时时间
*/
private int connetTimeout;
/**
* FTP上传文件时使用的最大时间,如不配置,则没有时间限制
*/
private int dataTimeout;
/**
* FTP 客户对象
*/
private FTPClient ftpClient = new FTPClient();
/**
* ftp家目录
*
*/
private String ftpHome = "";
/**
* 构造方法不允许外部调用,只允许FtpToolHelper类使用
*
* @param ftpConfigInfo
* @param ftp未加密的密码
* @param ftp重试的二次密码
*/
FtpTool(FtpConfigInfo ftpConfigInfo, String password, String tempFtpPassword)
throws FtpException
{
this.ftpServerIP = ftpConfigInfo.getFtpIP();
String ftpPort = ftpConfigInfo.getFtpPort();
// 端口不合法时,使用默认端口。
if (null == ftpPort || "".equals(ftpPort.trim()))
{
ftpPort = String.valueOf(FTP_DEFAULT_PORT);
}
try
{
this.ftpServerPort = Integer.parseInt(ftpPort);
}
catch (Exception e)
{
log.warn(KEY_WORD, "Get ftp server port failed, the exception:", e);
this.ftpServerPort = FTP_DEFAULT_PORT;
}
this.ftpUserName = ftpConfigInfo.getUserName();
this.ftpPassword = password;
try
{
this.connetTimeout = Integer.parseInt(ftpConfigInfo.getConnectTimeout());
this.dataTimeout = Integer.parseInt(ftpConfigInfo.getConnectTimeout());
}
catch (NumberFormatException e)
{
log.warn("Timeout is not number, use default 30 seconds. Exception:", e);
this.connetTimeout = DEFUALT_TIMEOUT_SECOND;
this.dataTimeout = DEFUALT_TIMEOUT_SECOND;
}
// 设置ftp连接的超时时间
ftpClient.setConnectTimeout(this.connetTimeout * NUM1000);
// 设置ftp数据连接的超时时间
ftpClient.setDataTimeout(this.dataTimeout * NUM1000);
log.info(KEY_WORD, "Prepare to connet ftp server[{}:{}]", ftpServerIP, ftpServerPort);
// 连接服务器
int reply = -1;
try
{
// 连接的时候要指定连接编码方式为UTF-8
ftpClient.setControlEncoding("UTF-8");
ftpClient.connect(this.ftpServerIP, this.ftpServerPort);
reply = ftpClient.getReplyCode();
}
catch (Exception ex)
{
AlarmAccess.record(composeAlarmInfo());
closeConnect();
log.warn("Failed to connect to server [{}:{}], the exception:", this.ftpServerIP, this.ftpServerPort, ex);
throw new FtpException(ex); // NOPMD by yKF18520 2010-03-02
}
// 如果连接失败,则抛出异常
if (!FTPReply.isPositiveCompletion(reply))
{
AlarmAccess.record(composeAlarmInfo());
log.warn(KEY_WORD, "Conect to ftp server failed! Ftp server ip :{}", this.ftpServerIP);
closeConnect();
throw new FtpException("");
}
login(tempFtpPassword);
ftpHome = this.getFtpWorkDIR();
// 连接成功恢复告警。
AlarmAccess.recover(composeAlarmInfo());
log.info(KEY_WORD, "Log in ftp server[{}] succeed,and current WorkDIR is:{}", this.ftpServerIP, getFtpWorkDIR());
}
/**
* 用户登录,如果这里用户登陆失败时,尝试用临时密码重连,如果还是失败,上报告警
*
* @param tempFtpPassword 临时密码
* @throws FtpException FTP异常
* @since PortalONE V200R002C08_API_Sprint13
*/
private void login(String tempFtpPassword)
throws FtpException
{
boolean result = false;
// 登录鉴权
try
{
result = ftpClient.login(this.ftpUserName, this.ftpPassword);
}
catch (IOException ex)
{
AlarmAccess.record(composeAlarmInfo());
log.warn(KEY_WORD, "Ftp server ip :{}. Login failed and the exception: ", this.ftpServerIP, ex);
closeConnect();
throw new FtpException(ex); // NOPMD by yKF18520 2010-03-02
}
// 统一密码修改功能会在修改密码时先将密码存放到临时表中,如果这里用户登陆失败时,尝试用临时密码重连
if (!result && null != tempFtpPassword)
{
this.ftpPassword = tempFtpPassword;
try
{
result = ftpClient.login(this.ftpUserName, this.ftpPassword);
}
catch (IOException ex)
{
AlarmAccess.record(composeAlarmInfo());
log.warn(KEY_WORD, "Ftp server ip :{}. Login failed and the exception:", this.ftpServerIP, ex);
closeConnect();
throw new FtpException(ex); // NOPMD by yKF18520 2010-03-02
}
}
// 登陆失败
if (!result)
{
AlarmAccess.record(composeAlarmInfo());
log.warn(KEY_WORD, "Login failed! Ftp server ip : {}", this.ftpServerIP);
closeConnect();
throw new FtpException("Login failed!");
}
}
/**
* 上传文件到FTP服务端指定目录
*
* @param srcFileName 上传的源文件,包括全路径
* @param destFileName 上传到服务端后的文件名,包括目标目录和目标文件名
* @throws FtpException FtpException
* @see [类、类#方法、类#成员]
*/
public void uploadFile(String srcFileName, String destFileName)
throws FtpException
{
log.info(KEY_WORD, "Start to upload file[{}] to [{}].", srcFileName, destFileName);
File srcFile = null;
// 开始输入参数检查
if (srcFileName == null || srcFileName.equals(""))
{
log.warn(KEY_WORD, "Src file name is null!");
throw new FtpException("");
}
else
{
srcFile = new File(srcFileName);
}
if (!srcFile.exists())
{
log.warn(KEY_WORD, "{} is not a file!", srcFileName);
throw new FtpException(srcFileName + " is not a file!");
}
else if (!srcFile.isFile())
{
log.warn(KEY_WORD, "{} is not a file!", srcFileName);
throw new FtpException(srcFileName + " is not a file!");
}
if (destFileName == null)
{
log.warn(KEY_WORD, "Dest file is null!");
throw new FtpException("Dest file is null!");
}
// 结束输入参数检查
// 传送文件
boolean result = false;
InputStream input = null;
try
{
// 设置传送格式
this.ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
input = new FileInputStream(srcFile);
// 删除目标文件
this.ftpClient.deleteFile(destFileName);
// 上传文件
result = this.ftpClient.storeFile(destFileName, input);
}
catch (IOException ex)
{
// 上传异常
File tempFile = new File(destFileName);
if (tempFile.exists())
{
try
{
// 删除上传产生的错误的临时文件
ftpClient.deleteFile(destFileName);
}
catch (IOException e)
{
log.warn(KEY_WORD, "delete remote file failed , and the exception:", ex);
}
}
log.warn(KEY_WORD, "Upload file failed, and the exception:", ex);
throw new FtpException("Upload file " + srcFileName + "to FTP server's dir:" + destFileName + "falied!", ex);
}
finally
{
try
{
// 关闭输入流
if (null != input)
{
input.close();
}
}
catch (IOException ex)
{
log.warn(KEY_WORD, "close input stream failed:, and the exception:", ex);
}
}
// 如果上传失败,那么抛出异常
if (!result)
{
log.warn(KEY_WORD, "Upload file faild!");
throw new FtpException("Upload file faild!");
}
// 打印完成信息
log.info(KEY_WORD, "Upload file succeed.");
}