FTP工具类
java实现
登陆FTP服务器
/**
* 获取FTPClient对象
*
* @param ftpHost FTP主机服务器
* @param ftpPassword FTP 登录密码
* @param ftpUserName FTP登录用户名
* @param ftpPort FTP端口 默认为21
* @param connectMode FTP连接模式 默认为21
* @return
*/
public static FTPClient getFTPClient(String ftpHost, String ftpUserName,String ftpPassword, int ftpPort,String connectMode) {
FTPClient ftpClient = new FTPClient();;
try {
ftpClient.connect(ftpHost, ftpPort);// 连接FTP服务器
ftpClient.login(ftpUserName, ftpPassword);// 登陆FTP服务器
ftpClient.setConnectTimeout(timeout);//设置连接超时时间
ftpClient.setDataTimeout(timeout);//设置数据超时时间
//被动模式
if ("PASV".equals(connectMode)) {
ftpClient.enterRemotePassiveMode();
ftpClient.enterLocalPassiveMode();
} else if ("PORT".equals(connectMode)) {
ftpClient.enterLocalActiveMode();
// ftpClient.enterRemoteActiveMode(host, port);
}
if (!FTPReply.isPositiveCompletion(ftpClient.getReplyCode())) {
System.out.println("未连接到FTP,用户名或密码错误。");
ftpClient.disconnect();
} else {
System.out.println("FTP连接成功。");
}
//设置命令传输编码
String fileEncoding = System.getProperty("file.encoding");
ftpClient.setControlEncoding(fileEncoding);
} catch (UnknownHostException e) {
System.out.println("FTP的IP地址可能错误,请正确配置。");
} catch (IllegalArgumentException e) {
System.out.println("FTP的端口错误,请正确配置。");
} catch (Exception e) {
System.out.println("与ftp服务器建立连接失败。");
}
return ftpClient;
}
上传文件
/**
* Description: 向FTP服务器上传文件
* @param ftpHost FTP服务器hostname
* @param ftpUserName 账号
* @param ftpPassword 密码
* @param ftpPort 端口
* @param connectMode FTP连接模式
* @param ftpPath FTP服务器中文件所在路径 格式: ftptest/aa
* @param fileName ftp文件名称
* @param input 文件流
* @return 成功返回true,否则返回false
*/
public static boolean uploadFile(String ftpHost, String ftpUserName, String ftpPassword, int ftpPort, String connectMode, String ftpPath, String fileName,InputStream input) {
boolean success = false;
FTPClient ftpClient = null;
String LOCAL_CHARSET = "GBK";
String SERVER_CHARSET = "ISO-8859-1";
try {
int reply;
ftpClient = getFTPClient(ftpHost, ftpUserName, ftpPassword, ftpPort ,connectMode);
reply = ftpClient.getReplyCode();
if (!FTPReply.isPositiveCompletion(reply)) {
ftpClient.disconnect();
return success;
}
ftpPath = new String(path.getBytes(LOCAL_CHARSET),SERVER_CHARSET);
// 创建并切换目录
if (null != ftpPath && !"".equals(ftpPath)) {
makeDirectorys(ftpPath, ftpClient);
ftpClient.changeWorkingDirectory(ftpPath);
}
String fileName = new String(fileName.getBytes(LOCAL_CHARSET), SERVER_CHARSET);
ftpClient.setControlEncoding("UTF-8"); // 中文支持
ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
ftpClient.storeFile(newFileName, input);
input.close();
ftpClient.logout();
success = true;
} catch (IOException e) {
e.printStackTrace();
} finally {
if (ftpClient.isConnected()) {
try {
ftpClient.disconnect();
} catch (IOException ioe) {
}
}
}
return success;
}
创建FTP目录
/**
* desc: 每次只能创建一级目录
*
* @param path
* @param ftpClient
* @throws IOException
*/
public static void makeDirectorys(String path, FTPClient ftpClient)
throws IOException {
String[] paths = path.split("/");
if (paths != null && paths.length > 1) {
StringBuilder s = new StringBuilder("");
for (int i = 0; i < paths.length; i++) {
if (paths[i] != null && paths[i].length() != 0) {
s = s.append("/").append(paths[i]);
ftpClient.makeDirectory(s.toString());
}
}
}
}
下载文件
/*
* 从FTP服务器下载文件
*
* @param ftpHost FTP IP地址
* @param ftpUserName FTP 用户名
* @param ftpPassword FTP用户名密码
* @param ftpPort FTP端口
* @param connectMode FTP连接模式
* @param ftpPath FTP服务器中文件所在路径 格式: ftptest/aa
* @param localPath 下载到本地的位置 格式:H:/download
* @param fileName 文件名称
*/
public static void downloadFtpFile(String ftpHost, String ftpUserName, String ftpPassword, int ftpPort, String connectMode, String ftpPath, String localPath, String fileName) {
FTPClient ftpClient = null;
try {
ftpClient = getFTPClient(ftpHost, ftpUserName, ftpPassword, ftpPort, connectMode);
ftpClient.setControlEncoding("UTF-8"); // 中文支持
ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
ftpClient.changeWorkingDirectory(ftpPath);
File localFile = new File(localPath + File.separatorChar + fileName);
OutputStream os = new FileOutputStream(localFile);
ftpClient.retrieveFile(fileName, os);
os.close();
ftpClient.logout();
} catch (FileNotFoundException e) {
System.out.println("没有找到" + ftpPath + "文件");
e.printStackTrace();
} catch (SocketException e) {
System.out.println("连接FTP失败.");
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
System.out.println("文件读取错误。");
}
}
登出FTP服务器
/**
* Description: 登出ftp服务器
*/
public void logoutFtpServer() {
if (ftpClient.isConnected()) {
try {
//todo ftpClient.completePendingCommand();//打开流操作之后必须,原因还需要深究
ftpClient.logout();
} catch (IOException e) {
System.out.println("与ftp服务器断开连接失败");
}finally {
if(ftpClient.isConnected()){
try {
ftpClient.disconnect();
} catch (IOException e) {
System.out.println("与ftp服务器断开连接失败");
}
}
}
}
}
断点续传
FTP常见状态码
1xx - 肯定的初步答复
这些状态代码指示一项操作已经成功开始,但客户端希望在继续操作新命令前得到另一个答复。
110 重新启动标记答复。
120 服务已就绪,在 nnn 分钟后开始。
125 数据连接已打开,正在开始传输。
150 文件状态正常,准备打开数据连接。
FTP 使用两个端口:21 用于发送命令,20 用于发送数据。状态代码 150 表示服务器准备在端口 20 上打开新连接,发送一些数据。
2xx - 肯定的完成答复
一项操作已经成功完成。客户端可以执行新命令。 200 命令确定。
202 未执行命令,站点上的命令过多。
211 系统状态,或系统帮助答复。
212 目录状态。
213 文件状态。
214 帮助消息。
215 NAME 系统类型,其中,NAME 是 Assigned Numbers 文档中所列的正式系统名称。
220 服务就绪,可以执行新用户的请求。
221 服务关闭控制连接。如果适当,请注销。
225 数据连接打开,没有进行中的传输。
226 关闭数据连接。请求的文件操作已成功(例如,传输文件或放弃文件)。
命令在端口 20 上打开数据连接以执行操作,如传输文件。该操作成功完成,数据连接已关闭。
227 进入被动模式 (h1,h2,h3,h4,p1,p2)。
230 用户已登录,继续进行。
250 请求的文件操作正确,已完成。
257 已创建“PATHNAME”。
3xx - 肯定的中间答复
该命令已成功,但服务器需要更多来自客户端的信息以完成对请求的处理。 331 用户名正确,需要密码。
332 需要登录帐户。
350 请求的文件操作正在等待进一步的信息。
4xx - 瞬态否定的完成答复
该命令不成功,但错误是暂时的。如果客户端重试命令,可能会执行成功。 421 服务不可用,正在关闭控制连接。如果服务确定它必须关闭,将向任何命令发送这一应答。
425 无法打开数据连接。
426 Connection closed; transfer aborted.
450 未执行请求的文件操作。文件不可用(例如,文件繁忙)。
451 请求的操作异常终止:正在处理本地错误。
452 未执行请求的操作。系统存储空间不够。
5xx - 永久性否定的完成答复
该命令不成功,错误是永久性的。如果客户端重试命令,将再次出现同样的错误。 500 语法错误,命令无法识别。这可能包括诸如命令行太长之类的错误。
501 在参数中有语法错误。
502 未执行命令。
503 错误的命令序列。
504 未执行该参数的命令。
530 未登录。
532 存储文件需要帐户。
550 未执行请求的操作。文件不可用(例如,未找到文件,没有访问权限)。
551 请求的操作异常终止:未知的页面类型。
552 请求的文件操作异常终止:超出存储分配(对于当前目录或数据集)。
553 未执行请求的操作。不允许的文件名。
常见的 FTP 状态代码及其原因
150 - FTP 使用两个端口:21 用于发送命令,20 用于发送数据。状态代码 150 表示服务器准备在端口 20 上打开新连接,发送一些数据。
226 - 命令在端口 20 上打开数据连接以执行操作,如传输文件。该操作成功完成,数据连接已关闭。
230 - 客户端发送正确的密码后,显示该状态代码。它表示用户已成功登录。
331 - 客户端发送用户名后,显示该状态代码。无论所提供的用户名是否为系统中的有效帐户,都将显示该状态代码。
421- too many connections普通ftp服务器对连接数做了限制
426 - 命令打开数据连接以执行操作,但该操作已被取消,数据连接已关闭。
530 - 该状态代码表示用户无法登录,因为用户名和密码组合无效。如果使用某个用户帐户登录,可能键入错误的用户名或密码,也可能选择只允许匿名访问。如果使用匿名帐户登录,IIS 的配置可能拒绝匿名访问
550 - 命令未被执行,因为指定的文件不可用。例如,要 GET 的文件并不存在,或试图将文件 PUT 到您没有写入权限的目录