import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPConnectionClosedException;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;
import org.apache.log4j.Logger;
import org.apache.log4j.spi.LoggerFactory;
import java.io.*;
import java.net.SocketException;
/**
* @ClassName: FtpUtil FTP操作工具类
* @Author: tanp
* @Description: 主要功能点:连接、登录、目录操作、文件下载、文件上传、指定目录或者文件删除、断点续传、断点下载;
* @Date: 2020/9/7 10:43
*/
public class FtpUtil {
private static final Logger logger = LoggerFactory.getLogger(FtpUtil.class);
/**
* 用户名
*/
private String username = null;
/**
* 密码
*/
private String password = null;
/**
* HOST
*/
private String hostname = null;
/**
* 端口
*/
private int port = 21;
/**
* FTP客户端
*/
private FTPClient client = null;
public FtpUtil() throws SocketException {
this.client = new FTPClient();
client.setKeepAlive(true);
client.setSoTimeout(600);
}
public FtpUtil(String ip, int port, String username, String password) throws SocketException {
this.hostname = ip;
this.port = port;
this.username = username;
this.password = password;
this.client = new FTPClient();
client.setControlEncoding("GBK");
}
/**
* 和FTP服务器建立连接
*/
public boolean connect() throws NullPointerException {
if (null == client){
throw new NullPointerException("FTP客户端尚未被初始化,请先实例化该类。");
}
try {
if (port > 0) {
client.connect(hostname, port);
} else {
client.connect(hostname);
}
if (!FTPReply.isPositiveCompletion(client.getReplyCode())) {
client.disconnect();
logger.error("FTP服务器拒绝建立连接。" + client.getReplyString());
return false;
} else {
//长连接
client.setKeepAlive(true);
//socket超时时间,设置底层TCP/IP层(FTP属于ARP层)超时时间。便于底层自己发送心跳包
client.setSoTimeout(1000);
//设置控制端口的心跳超时时间,便于自动发送控制端口心跳检测包
client.setControlKeepAliveTimeout(1000);
client.setControlKeepAliveReplyTimeout(1000);
return true;
}
} catch (SocketException e) {
logger.error("同FTP服务器建立连接失败", e);
return false;
} catch (IOException e1) {
logger.error("同FTP服务器建立连接通信失败", e1);
return false;
}
}
/**
* 登录到FTP服务器
*/
public boolean login() throws NullPointerException {
if (null == client){
throw new NullPointerException("FTP客户端尚未被初始化,请先实例化该类。");
}
//如果未建立连接
if (!client.isConnected()) {
//尝试连接
if (connect()) {
try {
return client.login(username, password);
} catch (FTPConnectionClosedException e) {
logger.error("FTP服务器强制断开连接,登录失败!", e);
return false;
} catch (IOException e) {
logger.error("网络异常,登录FTP服务器失败!", e);
return false;
}
}
}
return false;
}
/**
* FTP列表服务
*
* @throws NullPointerException FTPCLIETN尚未初始化
* @throws SocketException 尚未建立FTP连接
* @throws IOException 通信过程中出现网络异常
*/
public FTPFile[] list() throws NullPointerException, SocketException, IOException {
if (null == client){
throw new NullPointerException("FTP客户端尚未被初始化,请先实例化该类。");
}
if (!client.isConnected()) {
throw new SocketException("客户端尚未登录!");
}
return client.listFiles();
}
/**
* @param path 文件路径
* @return 指定文件路径的文件列表
*/
public FTPFile[] list(String path) {
try {
if (changDirectory(path)) {
return list();
}
} catch (NullPointerException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
/**
* @param path 需要改变的路径
* @throws NullPointerException FTP客户端尚未被实例化
* @throws SocketException 网络异常,客户端尚未与FTP建立连接
*/
public boolean changDirectory(String path) throws NullPointerException, IllegalArgumentException, IOException {
if (null == client){
throw new NullPointerException("FTP客户端尚未被初始化,请先实例化该类。");
}
if (null == path || path.isEmpty() || "".equals(path.trim())) {
throw new IllegalArgumentException("路径名不能为空!");
}
if (!client.isConnected()) {
throw new SocketException("客户端尚未登录!");
}
return client.changeWorkingDirectory(path);
}
/**
* @param fileName 需要下载的文件名
* @param localFullPath 本地完整的目录名(即需要保存到本地的哪个目录)
* @throws NullPointerException FTP客户端尚未被实例化
*/
public boolean download(String fileName, String localFullPath) throws NullPointerException, IOException {
if (null == client) {
throw new NullPointerException("FTP客户端尚未被初始化,请先实例化该类。");
}
if (StringUtils.isNullOrEmpty(fileName)) {
logger.warn("需要下载的文件或者目录名为空!");
return false;
}
if (StringUtils.isNullOrEmpty(localFullPath)) {
logger.warn("本地目标文件名或完整目录名为空!");
return false;
}
File file = new File(localFullPath + "/" + fileName + ".tmp");
boolean flag = false;
if (!file.exists()) {
try {
flag = file.createNewFile();
flag = true;
} catch (IOException e) {
logger.error("创建文件:" + localFullPath + "失败!", e);
return false;
}
} else {
flag = true;
}
OutputStream os = null;
try {
os = new FileOutputStream(file);
if (client.isConnected()) {
boolean f = client.retrieveFile(fileName, os);
if (f) {
os.flush();
}
}
} catch (FileNotFoundException e) {
logger.error("文件(" + localFullPath + ")不存在!", e);
return false;
} catch (IOException e) {
logger.error("从FTP服务器获取文件(" + fileName + "),过程出现网络错误!", e);
throw e;
} finally {
if (null != os) {
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return flag;
}
/**
* 删除FTP上的文件
*
* @param file 文件名
* @return 操作是否成功
*/
public boolean deleteFile(String file) {
if (null == client) {
logger.error("FTP客户端尚未被实例化。");
return false;
}
if (client.isConnected()) {
try {
client.deleteFile(file);
if (FTPReply.isPositiveCompletion(client.getReplyCode())) {
return true;
}
} catch (IOException e) {
logger.error("删除文件(" + file + "),失败。出现网络异常!", e);
return false;
}
}
return false;
}
/**
* 删除FTP服务器上指定的目录
*
* @param directory
*/
public boolean deleteDirectory(String directory) {
if (null == client) {
logger.error("FTP客户端尚未被实例化。");
return false;
}
if (client.isConnected()) {
try {
int code = client.dele(directory);
if (FTPReply.isPositiveCompletion(code)) {
return true;
}
} catch (IOException e) {
logger.error("删除文件(" + directory + "),失败。出现网络异常!", e);
return false;
}
}
return false;
}
/**
* 该方法完成建立连接和登录到FTP服务器两个操作,任意一个操作失败,则返回失败。否则返回成功
*
* @throws NullPointerException FTP客户端工具类尚未被实例化
*/
public boolean reconnect() {
if (null == client) {
throw new NullPointerException("FTP客户端尚未被初始化,请先实例化该类。");
}
if (client.isConnected()) {
try {
client.disconnect();
} catch (IOException e) {
logger.error("关闭同FTP服务器连接失败。");
}
}
if (connect()) {
return login();
}
return false;
}
public boolean login(String username, String password) {
if (null == client){
throw new NullPointerException("FTP客户端尚未被初始化,请先实例化该类。");
}
//如果未建立连接
if (!client.isConnected()) {
//尝试连接
if (connect()) {
logger.error("尝试重连FTP服务器失败!无法登录。");
return false;
}
}
try {
return client.login(username, password);
} catch (FTPConnectionClosedException e) {
logger.error("FTP服务器强制断开连接,登录失败!", e);
return false;
} catch (IOException e) {
logger.error("网络异常,登录FTP服务器失败!", e);
return false;
}
}
}