1. 概述

本文我们将学习 如何使用 Java 通过 SFTP 协议上传和下载文件

我们将分别使用三个不同的 Java 库来实现:JSch、SSHJ 和 Apache Commons VFS


2. 使用 JSch

JSch 是一个用于 Java 的 SSH2 实现库,支持 SFTP 文件传输。它简单易用,适合集成在需要远程文件操作的项目中。

2.1. Maven 配置

首先在 pom.xml 中添加 JSch 依赖:

<dependency>
    <groupId>com.jcraft</groupId>
    <artifactId>jsch</artifactId>
    <version>0.2.16</version>
</dependency>

最新版本可在 Maven Central 查看。

2.2. 初始化 JSch

JSch 支持密码认证和密钥认证。这里我们使用密码认证连接远程服务器:

private ChannelSftp setupJsch() throws JSchException {
    JSch jsch = new JSch();
    jsch.setKnownHosts("/Users/john/.ssh/known_hosts");
    Session jschSession = jsch.getSession(username, remoteHost);
    jschSession.setPassword(password);
    jschSession.connect();
    return (ChannelSftp) jschSession.openChannel("sftp");
}

变量定义如下:

private String remoteHost = "example.com";  // 示例域名
private String username = "admin";
private String password = "secure123";

生成 known_hosts 文件可使用如下命令:

ssh-keyscan -H -t rsa example.com >> known_hosts

2.3. 上传文件

使用 ChannelSftp.put() 方法上传文件:

@Test
public void whenUploadFileUsingJsch_thenSuccess() throws JSchException, SftpException {
    ChannelSftp channelSftp = setupJsch();
    channelSftp.connect();

    String localFile = "src/main/resources/sample.txt";
    String remoteDir = "remote_sftp_test/";

    channelSftp.put(localFile, remoteDir + "jschFile.txt");

    channelSftp.exit();
}

2.4. 下载文件

使用 ChannelSftp.get() 方法下载文件:

@Test
public void whenDownloadFileUsingJsch_thenSuccess() throws JSchException, SftpException {
    ChannelSftp channelSftp = setupJsch();
    channelSftp.connect();

    String remoteFile = "welcome.txt";
    String localDir = "src/main/resources/";

    channelSftp.get(remoteFile, localDir + "jschFile.txt");

    channelSftp.exit();
}

3. 使用 SSHJ

SSHJ 是另一个功能更现代、API 更清晰的 SSH/SFTP Java 客户端库,支持压缩、连接池等功能。

3.1. Maven 配置

添加 SSHJ 依赖:

<dependency>
    <groupId>com.hierynomus</groupId>
    <artifactId>sshj</artifactId>
    <version>0.38.0</version>
</dependency>

最新版本可在 Maven Central 查看。

3.2. 初始化 SSHJ

同样使用密码认证,并启用压缩:

private SSHClient setupSshj() throws IOException {
    SSHClient client = new SSHClient();
    client.addHostKeyVerifier(new PromiscuousVerifier());
    client.connect(remoteHost);
    client.useCompression();
    client.authPassword(username, password);
    return client;
}

3.3. 上传文件

使用 SFTPClient.put() 方法上传:

@Test
public void whenUploadFileUsingSshj_thenSuccess() throws IOException {
    SSHClient sshClient = setupSshj();
    SFTPClient sftpClient = sshClient.newSFTPClient();

    sftpClient.put(localFile, remoteDir + "sshjFile.txt");

    sftpClient.close();
    sshClient.disconnect();
}

变量定义如下:

private String localFile = "src/main/resources/input.txt";
private String remoteDir = "remote_sftp_test/";

3.4. 下载文件

使用 SFTPClient.get() 方法下载:

@Test
public void whenDownloadFileUsingSshj_thenSuccess() throws IOException {
    SSHClient sshClient = setupSshj();
    SFTPClient sftpClient = sshClient.newSFTPClient();

    sftpClient.get(remoteFile, localDir + "sshjFile.txt");

    sftpClient.close();
    sshClient.disconnect();
}

变量定义如下:

private String remoteFile = "welcome.txt";
private String localDir = "src/main/resources/";

4. 使用 Apache Commons VFS

Apache Commons VFS 提供统一的文件系统访问接口,底层使用 JSch 实现 SFTP。

4.1. Maven 配置

添加依赖:

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-vfs2</artifactId>
    <version>2.9.0</version>
</dependency>

最新版本可在 Maven Central 查看。

4.2. 上传文件

使用 FileObject.copyFrom() 方法上传:

@Test
public void whenUploadFileUsingApacheVfs_thenSuccess() throws IOException {
    FileSystemManager manager = VFS.getManager();

    FileObject local = manager.resolveFile(
      System.getProperty("user.dir") + "/" + localFile);
    FileObject remote = manager.resolveFile(
      "sftp://" + username + ":" + password + "@" + remoteHost + "/" + remoteDir + "vfsFile.txt");

    remote.copyFrom(local, Selectors.SELECT_SELF);

    local.close();
    remote.close();
}

4.3. 下载文件

同样使用 FileObject.copyFrom() 方法下载:

@Test
public void whenDownloadFileUsingApacheVfs_thenSuccess() throws IOException {
    FileSystemManager manager = VFS.getManager();

    FileObject local = manager.resolveFile(
      System.getProperty("user.dir") + "/" + localDir + "vfsFile.txt");
    FileObject remote = manager.resolveFile(
      "sftp://" + username + ":" + password + "@" + remoteHost + "/" + remoteFile);

    local.copyFrom(remote, Selectors.SELECT_SELF);

    local.close();
    remote.close();
}

5. 总结

✅ 本文介绍了三种常见的 Java 实现 SFTP 文件传输的方式:

特点
JSch 简单易用,但文档较少,社区活跃度下降
SSHJ API 更现代,支持压缩、连接池,推荐新项目使用
Apache VFS 提供统一的文件系统抽象,适合已有 VFS 集成的项目

⚠️ 注意:SFTP 操作涉及网络和权限,务必做好异常处理和资源释放。

完整代码示例已上传至 GitHub:GitHub 示例地址

如果你有自动化运维、文件同步、备份等需求,这几种方式都可以作为备选方案。选择时建议根据项目复杂度和维护成本权衡。


原始标题:Transferring a File Through SFTP in Java