JAVA의 jsch 라이브러리를 사용한 sftp 연결
목적
- 웹상(HTTP)에서 큰 파일을 다운로드/업로드 하기 위해 사용하는 프로토콜중 하나로 사용하기 위함.
- 파일 이어받기, 이어올리기가 가능해야한다.
예제
예제는 java application을 사용하여 파일 다운로드/업로드를 구현한 내 소스에서 발췌했다.
설정 (library 다운로드)
- jsch를 사용하여 sftp연결
<dependency>
<groupId>com.jcraft</groupId>
<artifactId>jsch</artifactId>
<version>0.1.54</version>
</dependency>
연결
JSch jSch = new JSch();
Session session;
ChannelSftp sftp;
try {
// 접속 정보 세팅
session = jSch.getSession(mainFrame.getDownloadInfo().getServerId(), mainFrame.getDownloadInfo().getServerIp(), mainFrame.getDownloadInfo().getServerPort());
session.setPassword(mainFrame.getDownloadInfo().getServerPassword());
Properties properties = new Properties();
properties.put("StrictHostKeyChecking", "no");
session.setConfig(properties);
session.connect();
// sftp 연결
Channel channel = session.openChannel("sftp");
channel.connect();
sftp = (ChannelSftp) channel;
} catch (JSchException jse) {
mainFrame.logError(jse.getMessage());
}
파일 업로드
try (
FileInputStream fis = new FileInputStream(file);
) {
// 필요한 만큼 스킵
if (skipByte != 0) {
// progressMonitor는 진행 상황을 표시하기 위함
progressMonitor.setTotalCount(skipByte);
fis.skip(skipByte);
}
// 위치 변경
sftp.cd(directory);
// 변경한 위치에 데이터 전송
// append 옵션으로 파일이 있을 경우 이어 붙힘
sftp.put(fis, remoteFileName, progressMonitor, ChannelSftp.APPEND);
FileUtil.deleteTempFile(remoteFileName);
} catch (SftpException se) {
if (se.getMessage().contains("SocketException")) {
FileUploadFrame.logError("서버 연결이 끊겼습니다.");
} else {
FileUploadFrame.logError(se.getMessage());
}
FileUploadFrame.upload.setEnabled(true);
return false;
} catch (Exception e) {
FileUploadFrame.logError(e.getMessage());
FileUploadFrame.upload.setEnabled(true);
return false;
} finally {
close();
}
파일 다운로드
try {
File downloadFile = findLocalFile();
FileOutputStream fos = new FileOutputStream(downloadFile, true);
// 다운로드 진행상황 설정
ProgressMonitorService progressMonitor = new ProgressMonitorService();
progressMonitor.setFileSize(requestRemoteFileSize());
progressMonitor.setTotalCount(downloadFile.length());
// fos에 다운로드한 파일 데이터 받음
// channelsftp의 resume 옵션으로 이어 받음.
// 마지막에 있는 downloadFile.length()는 skip할 데이터를 받는 파라미터, 현재 로컬 파일의 크기를 지정하면 된다.
sftp.get(mainFrame.getDownloadInfo().getFilePath(), fos, progressMonitor, ChannelSftp.RESUME, downloadFile.length());
fos.close();
if (checkValidation()) {
mainFrame.logInfo("유효한 파일입니다.");
} else {
mainFrame.logError("MD5가 일치 하지 않습니다.");
mainFrame.logInfo("포탈에서 다시 다운로드 받으시기 바랍니다.");
}
mainFrame.logInfo("Token 삭제 요청");
UrlCallUtil.callURL(mainFrame.getTokenDeleteURL(), "", "DELETE");
mainFrame.logInfo("Token 삭제 완료");
mainFrame.logInfo("다운로드 완료");
mainFrame.enableDownload();
} catch (SftpException se) {
if (se.getMessage().contains("SocketException")) {
mainFrame.logError("서버 연결이 끊겼습니다.");
} else {
mainFrame.logError(se.getMessage());
}
} catch (IOException ioe) {
mainFrame.logError(ioe.getMessage());
} finally {
close();
}
연결 해제
sftp.quit();
session.disconnect();