반응형
java에서 sftp를 사용하기 위해서는 apache common vfs를 사용하거나, jsch 사용하는 방법이 있다.
jsch 라이브러리를 사용하면 쉽게 개인키나 패스워드를 사용하여 sftp에 접속할 수 있고, 업로드나 다운로드를 할 수 있다.
maven repository
https://mvnrepository.com/artifact/com.jcraft/jsch
개인키, 공개키 생성
sftp 접속 시 아이디와 패스워드를 사용하지 않고, 아이디와 개인키, 공개키를 사용하면 보안에 좀 더 좋을 수 있다.
(aws의 s3 ftp 사용시에도 키 파일을 이용하여 접속하라고 권고하고 있다.)
1. 접속하려는 클라이언트가 되는 서버에서 아래 명령으로 개인키, 공개키를 생성한다.
ssh-keygen -P "" -m PEM -f 원하는키명
(윈도우, 리눅스 동일)
위 명령 실행 시 파일이 2개가 생성되는데, 생성된 키는 아래와 같다.
원하는키명 <- 개인키
원하는키명.pub <- 공개키
끝에 .pub가 붙은 파일이 공개키 파일이다.
접속하려는 서버 담당자에게 공개키 파일을 전달하고, 개인키는 sftp 접속 시 사용해야 하므로 잘 보관해둔다.
JSch 접속 예제 소스
package com.tistory.hitomis.util;
import com.jcraft.jsch.*;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Vector;
public class SFTPUtil {
private Session session = null;
private Channel channel = null;
private ChannelSftp channelSftp = null;
/**
* 서버와 연결에 필요한 값들을 가져와 초기화 시킴
*
* @param host 서버 주소
* @param userName 아이디
* @param password 패스워드
* @param port 포트번호
* @param privateKey 개인키
*/
public void init(String host, String userName, String password, int port, String privateKey) {
JSch jSch = new JSch();
try {
if(privateKey != null) {//개인키가 존재한다면
jSch.addIdentity(privateKey);
}
session = jSch.getSession(userName, host, port);
if(privateKey == null && password != null) {//개인키가 없다면 패스워드로 접속
session.setPassword(password);
}
// 프로퍼티 설정
java.util.Properties config = new java.util.Properties();
config.put("StrictHostKeyChecking", "no"); // 접속 시 hostkeychecking 여부
session.setConfig(config);
session.connect();
//sftp로 접속
channel = session.openChannel("sftp");
channel.connect();
} catch (JSchException e) {
e.printStackTrace();
}
channelSftp = (ChannelSftp) channel;
}
/**
* 디렉토리 생성
*
* @param dir 이동할 주소
* @param mkdirName 생성할 디렉토리명
*/
public void mkdir(String dir, String mkdirName) {
if (!this.exists(dir + "/" + mkdirName)) {
try {
channelSftp.cd(dir);
channelSftp.mkdir(mkdirName);
} catch (SftpException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 디렉토리( or 파일) 존재 여부
* @param path 디렉토리 (or 파일)
* @return
*/
public boolean exists(String path) {
Vector res = null;
try {
res = channelSftp.ls(path);
} catch (SftpException e) {
if (e.id == ChannelSftp.SSH_FX_NO_SUCH_FILE) {
return false;
}
}
return res != null && !res.isEmpty();
}
/**
* 파일 업로드
*
* @param dir 저장할 디렉토리
* @param file 저장할 파일
* @return 업로드 여부
*/
public boolean upload(String dir, File file) {
boolean isUpload = false;
SftpATTRS attrs;
FileInputStream in = null;
try {
in = new FileInputStream(file);
channelSftp.cd(dir);
channelSftp.put(in, file.getName());
// 업로드했는지 확인
if (this.exists(dir +"/"+file.getName())) {
isUpload = true;
}
} catch (SftpException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return isUpload;
}
/**
* 파일 다운로드
*
* @param dir 다운로드 할 디렉토리
* @param downloadFileName 다운로드 할 파일
* @param path 다운로드 후 로컬에 저장될 경로(파일명)
*/
public void download(String dir, String downloadFileName, String path) {
InputStream in = null;
FileOutputStream out = null;
try {
channelSftp.cd(dir);
in = channelSftp.get(downloadFileName);
} catch (SftpException e) {
e.printStackTrace();
}
try {
out = new FileOutputStream(new File(path));
int i;
while ((i = in.read()) != -1) {
out.write(i);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
out.close();
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 연결 종료
*/
public void disconnection() {
channelSftp.quit();
session.disconnect();
}
}
사용방법 예제 소스
package com.tistory.hitomis;
import com.tistory.hitomis.util.SFTPUtil;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* 테스트를 위한 클래스
*/
public class JavaTest {
public static void main(String[] args) {
final SFTPUtil sftpUtil = new SFTPUtil();
final String host = "접속할 서버 아이피";
final String userName = "접속할 아이디";
final int port = 22;
final String uploadPath = "업로드경로";
final String downloadPath = "다운로드경로";
final String privateKey = "개인키경로/파일명";
// 업로드 시 업로드 폴더 아래에
// 현재 날짜 년월일을 생성하고 그 아래 올리기 위한 날짜 변수
final Date today = new Date();
final SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
// 접속
sftpUtil.init(host, userName, null, port, privateKey);
// 업로드 테스트
File uploadfile = new File("업로드할 경로+파일명"); // 파일 객체 생성
String mkdirPath = sdf.format(today); //현재날짜 년월일
sftpUtil.mkdir(uploadPath, mkdirPath); // 업로드경로에 현재날짜 년월일 폴더 생성
boolean isUpload = sftpUtil.upload(uploadPath+mkdirPath, uploadfile); //업로드
System.out.println("isUpload -" + isUpload); // 업로드 여부 확인
/* 다운로드 테스트 */
sftpUtil.download(downloadPath, "다운로드파일명", "로컬에저장할경로+파일명");
File downloadFile = new File("로컬에저장할경로+파일명");
if (downloadFile.exists()) {
System.out.println("다운로드 완료");
System.out.println(downloadFile.getPath());
System.out.println(downloadFile.getName());
}
// 업로드 다운로드 수행 후 꼭 연결을 끊어줘야 한다!!
sftpUtil.disconnection();
}
}
반응형
'개발 > java' 카테고리의 다른 글
Java Generics (0) | 2022.02.25 |
---|---|
Stream 예제 (0) | 2022.02.06 |
현재 날짜 출력, 시간 원하는 형태로 출력, 날짜 포맷 (0) | 2021.01.18 |
System으로 연산 소요 시간 구하기 (0) | 2021.01.18 |
StringBuffer로 문자열 수정, 변경, 추가 (0) | 2021.01.17 |
댓글