- 使用 Apache Commons Net (最常用、最稳定):这是社区中最流行、功能最全面的 FTP 客户端库。
- 使用 JSch (用于 SFTP):虽然 SFTP (SSH File Transfer Protocol) 名字里有 FTP,但它运行在 SSH 协议之上,比传统的 FTP (FTP over port 21) 安全得多,在现代应用中,强烈推荐使用 SFTP 替代 FTP。
- 使用 Java 原生 FTPClient (不推荐):Java 标准库中并没有一个直接、好用的 FTP 客户端,这个方法主要是为了展示 Java 的网络编程能力,但实际开发中极少使用,因为它复杂且功能有限。
准备工作:添加 Maven 依赖
无论使用哪种方法,你都需要在项目中添加相应的库依赖,这里以 Maven 为例。

Apache Commons Net (用于 FTP)
在你的 pom.xml 文件中添加:
<dependency>
<groupId>commons-net</groupId>
<artifactId>commons-net</artifactId>
<version>3.9.0</version> <!-- 请使用最新版本 -->
</dependency>
JSch (用于 SFTP)
在你的 pom.xml 文件中添加:
<dependency>
<groupId>com.jcraft</groupId>
<artifactId>jsch</artifactId>
<version>0.1.55</version> <!-- 请使用最新版本 -->
</dependency>
使用 Apache Commons Net (FTP)
这是最经典和直接的方法。
核心步骤
- 创建
FTPClient实例。 - 连接到 FTP 服务器 (
connect())。 - 登录 (
login())。 - 设置文件传输模式:二进制模式 (
setFileType(FTP.BINARY_FILE_TYPE)) 对于上传图片、压缩包、可执行文件等至关重要,可以防止文件损坏。 - 进入服务器上的目标目录 (
changeWorkingDirectory())。 - 上传文件 (
storeFile()或storeFileStream())。 - 断开连接 (
logout()和disconnect()),并处理异常。
完整代码示例
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPReply;
import java.io.FileInputStream;
import java.io.IOException;
public class FtpUploader {
public static void main(String[] args) {
String server = "ftp.yourserver.com";
int port = 21;
String user = "your_username";
String pass = "your_password";
// 本地文件路径
String localFilePath = "C:/path/to/your/localfile.txt";
// 远程服务器上的目标路径
String remoteFilePath = "/path/on/server/remotefile.txt";
FTPClient ftpClient = new FTPClient();
try {
// 1. 连接到服务器
ftpClient.connect(server, port);
int reply = ftpClient.getReplyCode();
if (!FTPReply.isPositiveCompletion(reply)) {
System.err.println("FTP server refused connection.");
return;
}
System.out.println("Connected to FTP server: " + server);
// 2. 登录
if (!ftpClient.login(user, pass)) {
System.err.println("Login failed. Check username/password.");
return;
}
System.out.println("Login successful.");
// 3. 设置文件传输模式为二进制,防止文件损坏
ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
// 4. 设置缓冲区大小
ftpClient.setBufferSize(1024 * 1024); // 1MB buffer
// 5. 进入远程目录 (如果不存在,需要先创建)
String remoteDir = "/path/on/server";
if (!ftpClient.changeWorkingDirectory(remoteDir)) {
System.out.println("Remote directory does not exist. Creating: " + remoteDir);
// 创建多级目录
String[] dirs = remoteDir.split("/");
String tempPath = "";
for (String dir : dirs) {
if (dir.isEmpty()) continue;
tempPath += "/" + dir;
if (!ftpClient.changeWorkingDirectory(tempPath)) {
if (!ftpClient.makeDirectory(tempPath)) {
System.err.println("Failed to create directory: " + tempPath);
return;
}
ftpClient.changeWorkingDirectory(tempPath);
}
}
}
// 6. 上传文件
try (FileInputStream fis = new FileInputStream(localFilePath)) {
System.out.println("Uploading file to: " + remoteFilePath);
boolean success = ftpClient.storeFile(remoteFilePath, fis);
if (success) {
System.out.println("File uploaded successfully.");
} else {
System.err.println("File upload failed. Reply: " + ftpClient.getReplyString());
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
// 7. 登出并断开连接
try {
if (ftpClient.isConnected()) {
ftpClient.logout();
ftpClient.disconnect();
System.out.println("Disconnected from FTP server.");
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
}
使用 JSch (SFTP - 强烈推荐)
SFTP 是通过 SSH 协议传输文件,所有数据都是加密的,比 FTP 安全得多。

核心步骤
- 创建
JSch实例。 - 创建
Session并配置主机、端口、用户名。 - 使用私钥或密码配置
Session。 - 连接
Session(connect())。 - 打开
ChannelSftp通道 (openChannel("sftp"))。 - 连接通道 (
connect())。 - 上传文件 (
put())。 - 断开通道和
Session(disconnect())。
完整代码示例 (使用密码)
import com.jcraft.jsch.*;
public class SftpUploader {
public static void main(String[] args) {
String host = "sftp.yourserver.com";
int port = 22; // SFTP 默认端口是 22
String user = "your_username";
String password = "your_password";
// 本地文件路径
String localFilePath = "C:/path/to/your/localfile.txt";
// 远程服务器上的目标路径
String remoteFilePath = "/path/on/server/remotefile.txt";
Session session = null;
ChannelSftp channelSftp = null;
try {
// 1. 创建 JSch 实例
JSch jsch = new JSch();
session = jsch.getSession(user, host, port);
session.setPassword(password);
// 2. 配置主机密钥检查 (第一次连接时需要)
// java.lang.RuntimeException: UnknownHostKey: xxx
// 为了方便开发,可以禁用严格的主机密钥检查,但生产环境不推荐!
java.util.Properties config = new java.util.Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
// 3. 连接 Session
System.out.println("Connecting to SFTP server...");
session.connect();
System.out.println("Connected.");
// 4. 打开 SFTP 通道
Channel channel = session.openChannel("sftp");
channel.connect();
System.out.println("SFTP channel opened.");
channelSftp = (ChannelSftp) channel;
// 5. 上传文件
System.out.println("Uploading file to: " + remoteFilePath);
channelSftp.put(localFilePath, remoteFilePath, ChannelSftp.OVERWRITE);
System.out.println("File uploaded successfully.");
} catch (JSchException | SftpException e) {
e.printStackTrace();
} finally {
// 6. 断开连接
if (channelSftp != null) {
channelSftp.disconnect();
System.out.println("SFTP channel disconnected.");
}
if (session != null) {
session.disconnect();
System.out.println("Session disconnected.");
}
}
}
}
使用 Java 原生 Socket (不推荐)
此方法不依赖任何第三方库,直接使用 Java 的 Socket 和 InputStream/OutputStream 与 FTP 服务器交互。代码非常繁琐,需要手动处理 FTP 协议的文本指令和响应码,极易出错,仅用于学习 FTP 协议本身。
核心思路
- 通过
Socket连接到 FTP 服务器的 21 端口。 - 从
Socket的InputStream读取服务器的响应码(如220服务就绪,331用户名正确,需要密码)。 - 通过
Socket的OutputStream发送 FTP 命令(如USER username,PASS password,PASV,STOR filename.txt)。 - 每次发送命令后,都必须读取服务器的响应。
- 对于文件数据传输,需要使用
PASV命令进入被动模式,获取一个数据连接的 IP 和端口,然后建立新的Socket来传输文件内容。
由于代码量巨大且复杂,这里不提供完整示例,如果你对此感兴趣,可以搜索 "Java raw FTP client example" 查看相关实现,但请记住,实际项目中请避免使用这种方式。
总结与对比
| 特性 | Apache Commons Net (FTP) | JSch (SFTP) | Java 原生 Socket (FTP) |
|---|---|---|---|
| 安全性 | 低 (数据明文传输) | 高 (SSH 加密传输) | 低 (数据明文传输) |
| 易用性 | 高 (封装良好,API 简单) | 高 (API 相对直观) | 极低 (需要手动处理协议) |
| 功能 | 强大 (支持 FTP/FTPS) | 强大 (支持 SFTP/SCP) | 基础 (仅实现最基本命令) |
| 依赖 | 需要 commons-net jar 包 |
需要 jsch jar 包 |
无需任何第三方库 |
| 推荐度 | ⭐⭐⭐☆☆ (如果必须用 FTP) | ⭐⭐⭐⭐⭐ (现代应用首选) | ⭐☆☆☆☆ (仅用于学习) |
最终建议
- 优先选择 SFTP:如果你的服务器支持,请毫不犹豫地选择 JSch 进行 SFTP 文件传输,它的安全性是 FTP 无法比拟的,是现代软件开发的行业标准。
- 如果只能用 FTP,使用 Commons Net:如果你的服务器环境老旧,只支持传统的 FTP,
Apache Commons Net是最稳定、最可靠的选择。 - 避免使用原生实现:除非你有特殊需求或想深入理解 FTP 协议,否则不要用 Java 原生 Socket 自己实现,它会浪费你大量的开发时间,并且引入难以发现的 Bug。

