Java를 사용하여 SFTP에 연결, 파일 목록, 업로드 및 다운로드 방법에 대해 설명합니다.
이 기사에서는 SFTP 서버에 연결하고 상호 작용하는 Java 코드를 작성하는 방법에 대해 설명합니다. SFTP는 널리 사용되는 표준적이고 안전한 프로토콜이며, 주요 목적은 안전한 파일 및 데이터 전송을 제공하는 것입니다. 서버에 연결할 때 필요한 몇 가지 간단한 절차를 배울 뿐이므로 이 기사를 끝까지 읽는 것으로 간단하게 SFTP 서버를 활용할 수 있게 될 겁니다.
요구 사항
SFTP 서버에 연결하는 데 사용되는 몇 가지 Java 라이브러리가 있습니다. 여기서는 Java만으로 SSH2를 구현 한 Jsch를 사용합니다. 다음 예제는 Java 프로젝트에 JSCH를 추가하는 방법의 일부입니다:
Maven을 사용하는 경우:
<dependency>
<groupId>com.github.mwiede</groupId>
<artifactId>jsch</artifactId>
<version>0.2.0</version>
</dependency>
Gradle을 사용하는 경우:
implementation 'com.github.mwiede:jsch:0.2.0'
SFTP에 연결
이 기사에서는 SFTP 서버에 연결하는 데 필요한 모든 정보를 URI 형식으로 저장된 SFTPTOGO_URL이라는 환경 변수를 사용합니다: sftp://user:password@host
이 변수는 URI.parse을 이용하여 URI 부분을 추출하고, 원격 서버의 호스트키는 ~/.ssh/known_hosts
를 사용하여 자동으로 확인됩니다.
SftpClient 클래스의 인스턴스를 작성할 때에, 호스트, 유저명 및 옵션으로 포트 (디폴트는 22)를 건네줍니다. 암호로 인증하려면 authPassword
함수를 사용하면 되며, 공개 키 인증을 사용 해 인증하려면 개인 키에 대한 경로와 경로 문자열을 authKey
함수에 전달합니다.
package com.sftptogo;
import com.jcraft.jsch.*;
import com.sftptogo.util.Util;
import java.util.Properties;
import java.util.Vector;
/**
* A simple SFTP client using JSCH http://www.jcraft.com/jsch/
*/
public final class SftpClient {
private final String host;
private final int port;
private final String username;
private final JSch jsch;
private ChannelSftp channel;
private Session session;
/**
* @param host remote host
* @param port remote port
* @param username remote username
*/
public SftpClient(String host, int port, String username) {
this.host = host;
this.port = port;
this.username = username;
jsch = new JSch();
}
/**
* Use default port 22
*
* @param host remote host
* @param username username on host
*/
public SftpClient(String host, String username) {
this(host, 22, username);
}
/**
* Authenticate with remote using password
*
* @param password password of remote
* @throws JSchException If there is problem with credentials or connection
*/
public void authPassword(String password) throws JSchException {
session = jsch.getSession(username, host, port);
//disable known hosts checking
//if you want to set knows hosts file You can set with jsch.setKnownHosts("path to known hosts file");
var config = new Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
session.setPassword(password);
session.connect();
channel = (ChannelSftp) session.openChannel("sftp");
channel.connect();
}
public void authKey(String keyPath, String pass) throws JSchException {
jsch.addIdentity(keyPath, pass);
session = jsch.getSession(username, host, port);
//disable known hosts checking
//if you want to set knows hosts file You can set with jsch.setKnownHosts("path to known hosts file");
var config = new Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
session.connect();
channel = (ChannelSftp) session.openChannel("sftp");
channel.connect();
}
}
파일 목록
연결이 완료되면 원격 SFTP 서버의 파일 목록을 얻을 수 있습니다. 래퍼 함수 listFiles
는 채널의 ls
함수를 호출하여 원격 파일 목록을 가져오고 이를 반복하여 각 파일의 사용 권한, 파일 이름 및 크기를 표시합니다.
/**
* List all files including directories
*
* @param remoteDir Directory on remote from which files will be listed
* @throws SftpException If there is any problem with listing files related to permissions etc
* @throws JSchException If there is any problem with connection
*/
@SuppressWarnings("unchecked")
public void listFiles(String remoteDir) throws SftpException, JSchException {
if (channel == null) {
throw new IllegalArgumentException("Connection is not available");
}
System.out.printf("Listing [%s]...%n", remoteDir);
channel.cd(remoteDir);
Vector<ChannelSftp.LsEntry> files = channel.ls(".");
for (ChannelSftp.LsEntry file : files) {
var name = file.getFilename();
var attrs = file.getAttrs();
var permissions = attrs.getPermissionsString();
var size = Util.humanReadableByteCount(attrs.getSize());
if (attrs.isDir()) {
size = "PRE";
}
System.out.printf("[%s] %s(%s)%n", permissions, name, size);
}
}
파일 업로드
다음 단계는 파일 업로드입니다. 이 클래스의 uploadFile
은 두 개의 인수로 사용되며 localPath(업로드할 파일)와 remotePath(서버의 업로드 대상)입니다. 호출의 예는 다음과 같습니다. client.uploadFile("./local.txt", "/remote.txt");
/**
* Upload a file to remote
*
* @param localPath full path of location file
* @param remotePath full path of remote file
* @throws JSchException If there is any problem with connection
* @throws SftpException If there is any problem with uploading file permissions etc
*/
public void uploadFile(String localPath, String remotePath) throws JSchException, SftpException {
System.out.printf("Uploading [%s] to [%s]...%n", localPath, remotePath);
if (channel == null) {
throw new IllegalArgumentException("Connection is not available");
}
channel.put(localPath, remotePath);
}
파일 다운로드
마지막은 파일 다운로드뿐입니다. downloadFile
함수는 remotePath(다운로드 할 파일)와 localPath(파일이 다운로드 될 위치)의 2 개의 인수를 취하고 있습니다. client.downloadFile("/remote.txt", "./download.txt")
와 같이 함수를 호출하게 됩니다.
/**
* Download a file from remote
*
* @param remotePath full path of remote file
* @param localPath full path of where to save file locally
* @throws SftpException If there is any problem with downloading file related permissions etc
*/
public void downloadFile(String remotePath, String localPath) throws SftpException {
System.out.printf("Downloading [%s] to [%s]...%n", remotePath, localPath);
if (channel == null) {
throw new IllegalArgumentException("Connection is not available");
}
channel.get(remotePath, localPath);
}
마지막으로
이것으로 완료입니다! 이 프로그램을 처음부터 끝까지 실행하고 싶다면 프로젝트를 구축과 실행방법에 대해 여기에 있는 설명을 따라하세요.
package com.sftptogo;
import com.jcraft.jsch.*;
import com.sftptogo.util.Util;
import java.util.Properties;
import java.util.Vector;
/**
* A simple SFTP client using JSCH http://www.jcraft.com/jsch/
*/
public final class SftpClient {
private final String host;
private final int port;
private final String username;
private final JSch jsch;
private ChannelSftp channel;
private Session session;
/**
* @param host remote host
* @param port remote port
* @param username remote username
*/
public SftpClient(String host, int port, String username) {
this.host = host;
this.port = port;
this.username = username;
jsch = new JSch();
}
/**
* Use default port 22
*
* @param host remote host
* @param username username on host
*/
public SftpClient(String host, String username) {
this(host, 22, username);
}
/**
* Authenticate with remote using password
*
* @param password password of remote
* @throws JSchException If there is problem with credentials or connection
*/
public void authPassword(String password) throws JSchException {
session = jsch.getSession(username, host, port);
//disable known hosts checking
//if you want to set knows hosts file You can set with jsch.setKnownHosts("path to known hosts file");
var config = new Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
session.setPassword(password);
session.connect();
channel = (ChannelSftp) session.openChannel("sftp");
channel.connect();
}
public void authKey(String keyPath, String pass) throws JSchException {
jsch.addIdentity(keyPath, pass);
session = jsch.getSession(username, host, port);
//disable known hosts checking
//if you want to set knows hosts file You can set with jsch.setKnownHosts("path to known hosts file");
var config = new Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
session.connect();
channel = (ChannelSftp) session.openChannel("sftp");
channel.connect();
}
/**
* List all files including directories
*
* @param remoteDir Directory on remote from which files will be listed
* @throws SftpException If there is any problem with listing files related to permissions etc
* @throws JSchException If there is any problem with connection
*/
@SuppressWarnings("unchecked")
public void listFiles(String remoteDir) throws SftpException, JSchException {
if (channel == null) {
throw new IllegalArgumentException("Connection is not available");
}
System.out.printf("Listing [%s]...%n", remoteDir);
channel.cd(remoteDir);
Vector<ChannelSftp.LsEntry> files = channel.ls(".");
for (ChannelSftp.LsEntry file : files) {
var name = file.getFilename();
var attrs = file.getAttrs();
var permissions = attrs.getPermissionsString();
var size = Util.humanReadableByteCount(attrs.getSize());
if (attrs.isDir()) {
size = "PRE";
}
System.out.printf("[%s] %s(%s)%n", permissions, name, size);
}
}
/**
* Upload a file to remote
*
* @param localPath full path of location file
* @param remotePath full path of remote file
* @throws JSchException If there is any problem with connection
* @throws SftpException If there is any problem with uploading file permissions etc
*/
public void uploadFile(String localPath, String remotePath) throws JSchException, SftpException {
System.out.printf("Uploading [%s] to [%s]...%n", localPath, remotePath);
if (channel == null) {
throw new IllegalArgumentException("Connection is not available");
}
channel.put(localPath, remotePath);
}
/**
* Download a file from remote
*
* @param remotePath full path of remote file
* @param localPath full path of where to save file locally
* @throws SftpException If there is any problem with downloading file related permissions etc
*/
public void downloadFile(String remotePath, String localPath) throws SftpException {
System.out.printf("Downloading [%s] to [%s]...%n", remotePath, localPath);
if (channel == null) {
throw new IllegalArgumentException("Connection is not available");
}
channel.get(remotePath, localPath);
}
/**
* Delete a file on remote
*
* @param remoteFile full path of remote file
* @throws SftpException If there is any problem with deleting file related to permissions etc
*/
public void delete(String remoteFile) throws SftpException {
System.out.printf("Deleting [%s]...%n", remoteFile);
if (channel == null) {
throw new IllegalArgumentException("Connection is not available");
}
channel.rm(remoteFile);
}
/**
* Disconnect from remote
*/
public void close() {
if (channel != null) {
channel.exit();
}
if (session != null && session.isConnected()) {
session.disconnect();
}
}
}
Java를 사용하여 SFTP에 연결할 수 있었습니다. 축하합니다!
다른 코드 샘플은Github에서 꼭 확인하십시오.