# Java通过SFTP处理文件三种方法,支持密钥文件登陆

# 1 前言

通过SFTP来访问文件是经常遇到的场景,比如需要从别人的服务拿文件等。本文介绍三种方式。

# 2 JSch

先准备一些常量,以便后续使用:

// 主机,IP或域名
private static final String HOST = "xxx.xxx.xxx.xxx";
// 端口
private static final int PORT = 22;
// 用户名
private static final String USERNAME = "pkslow";
// 密码
private static final String PASSWORD = "pkslow-password";
// 要上传或读取远端文件
private static final String REMOTE_FILENAME = "/root/pkslow-sftp/SftpMain.java";
// 要上传的本地文件
private static final String LOCAL_FILENAME = "/Users/pkslow/SftpMain.java";
// 下载文件的存放目录
private static final String LOCAL_DOWNLOAD_FOLDER = "/Users/pkslow/sftp/";

引入依赖:

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

Java代码如下:

private static void jsch() throws JSchException, SftpException {
  JSch jSch = new JSch();
  // 创建session
  Session session = jSch.getSession(USERNAME, HOST, PORT);
  session.setConfig("StrictHostKeyChecking", "no");
  session.setPassword(PASSWORD);
  session.connect();

  // 创建channel
  ChannelSftp channelSftp = (ChannelSftp) session.openChannel("sftp");
  channelSftp.connect();

  // 上传文件
  channelSftp.put(LOCAL_FILENAME, REMOTE_FILENAME);
  // 下载文件
  channelSftp.get(REMOTE_FILENAME,LOCAL_DOWNLOAD_FOLDER + "SftpMain-jsch.java");
  // 删除远程服务器的文件
  channelSftp.rm(REMOTE_FILENAME);

  // 退出并结束会话
  channelSftp.exit();
  session.disconnect();
}

设置session.setConfig("StrictHostKeyChecking", "no")是为了解决这个问题:com.jcraft.jsch.JSchException: UnknownHostKey (opens new window)

想通过Private Key来登陆请参考:Can we use JSch for SSH key-based communication? (opens new window)

# 3 SSHJ

引入依赖:

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

Java代码如下:

private static void sshj() throws IOException {
  // 创建SSH客户端
  SSHClient sshClient = new SSHClient();
  sshClient.addHostKeyVerifier(new PromiscuousVerifier());
  sshClient.connect(HOST);
  sshClient.authPassword(USERNAME, PASSWORD);
  //创建SFTP客户端
  SFTPClient sftpClient = sshClient.newSFTPClient();
  //上传文件
  sftpClient.put(LOCAL_FILENAME, REMOTE_FILENAME);
  // 下载文件
  sftpClient.get(REMOTE_FILENAME,LOCAL_DOWNLOAD_FOLDER + "SftpMain-sshj.java");
  // 删除远程服务器的文件
  sftpClient.rm(REMOTE_FILENAME);
	// 结束与退出
  sftpClient.close();
  sshClient.disconnect();
}

通过Private Key登陆《SSHJ Example of Public Key Auth from File (opens new window)》:

private static void sshjWithKey() throws IOException {
  SSHClient sshClient = new SSHClient();
  sshClient.addHostKeyVerifier(new PromiscuousVerifier());
  sshClient.connect(HOST);
  KeyProvider keys = sshClient.loadKeys("/Users/pkslow/.ssh/id_rsa");
  sshClient.authPublickey(USERNAME, keys);
  SFTPClient sftpClient = sshClient.newSFTPClient();
  sftpClient.put(LOCAL_FILENAME, REMOTE_FILENAME);
  sftpClient.get(REMOTE_FILENAME,LOCAL_DOWNLOAD_FOLDER + "SftpMain-sshj-withKey.java");
  sftpClient.rm(REMOTE_FILENAME);

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

# 4 Apache Commons VFS

引入依赖:

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

Java代码如下:

private static void apacheVFS() throws FileSystemException, URISyntaxException {
  FileSystemManager manager = VFS.getManager();
  FileObject localUpload = manager.resolveFile(LOCAL_FILENAME);
  URI remoteFileURI = new URI("sftp", USERNAME + ":" + PASSWORD, HOST, -1, REMOTE_FILENAME, null, null);

  FileObject remote = manager.resolveFile(remoteFileURI);

  remote.copyFrom(localUpload, Selectors.SELECT_SELF);

  FileObject localDownload = manager.resolveFile(LOCAL_DOWNLOAD_FOLDER + "SftpMain-apache-VFS.java");
  localDownload.copyFrom(remote, Selectors.SELECT_SELF);

  remote.delete();

  localUpload.close();
  localDownload.close();
  remote.close();
}

# 5 总结

本文介绍了Java处理SFTP文件的三种方法,直接贴上代码,方便大家参考使用。

上次更新: 2023/8/18 23:39:36