[JAVA] 자바 SFTP 파일 업로드, 파일 다운로드 (jsch 라이브러리 사용방법)
자바 FTP 파일 업로드, 다운로드를 구현하기 위해서 FTPSClient 사용하려고 했는데(관련 라이브러리 파일은 commons-net-2.2.jar) FTPSClient 는 SFTP 접속을 할 수 없었다.
아래처럼 SSH-2.0-OpenSSH_7.4 오류가 발생하면 SFTP 이므로 접속이 안되는 경우다.
|
org.apache.commons.net.MalformedServerReplyException: Could not parse response code.
Server Reply: SSH-2.0-OpenSSH_7.4
at org.apache.commons.net.ftp.FTP.__getReply(FTP.java:316)
at org.apache.commons.net.ftp.FTP._connectAction_(FTP.java:365)
at org.apache.commons.net.ftp.FTPClient._connectAction_(FTPClient.java:630)
at org.apache.commons.net.SocketClient.connect(SocketClient.java:164)
at org.apache.commons.net.SocketClient.connect(SocketClient.java:184)
|
SFTP 접속을 하기 위해서는 jsch 라이브러리를 사용하면 된다. 관련 라이브러리 파일은 jsch-0.1.49.jar 이고, 다음 주소에서 다운로드 받을 수 있다. https://mvnrepository.com/artifact/com.jcraft/jsch/0.1.49
우선 JSchWrapper 라는 클래스를 만들었다.
|
import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.util.Properties;
import com.jcraft.jsch.Channel; import com.jcraft.jsch.ChannelSftp; import com.jcraft.jsch.JSch; import com.jcraft.jsch.JSchException; import com.jcraft.jsch.Session;
public class JSchWrapper {
private Session jschSession = null; private Channel channel = null; private ChannelSftp channelSftp = null;
/** * 파일 업로드 * * @param fileName * @param dirPath * @throws Exception */ public boolean uploadFile(String fileName, String dirPath) throws Exception { boolean isSuccess = false;
FileInputStream fis = null;
try { // 대상폴더 이동 channelSftp.cd(dirPath);
File file = new File(fileName); fis = new FileInputStream(file);
// 파일 업로드 channelSftp.put(fis, file.getName()); isSuccess = true;
System.out.println(“File uploaded : “ + file.getAbsolutePath() + ” => “ + dirPath + “/” + file.getName());
} catch (Exception e) { throw e;
} finally { close(fis); }
return isSuccess; }
/** * 파일 다운로드 * * @param remoteFilePath * @param localDirPath * @param overwrite * @return * @throws Exception */ public boolean downloadFile(String remoteFilePath, String localDirPath, boolean overwrite) throws Exception { if (remoteFilePath == null || remoteFilePath.length() == 0) { return false; }
boolean isSuccess = false;
byte[] buffer = new byte[1024];
BufferedInputStream bis = null; FileOutputStream fos = null; BufferedOutputStream bos = null;
try { if (remoteFilePath.indexOf(“\\”) > -1) { remoteFilePath = remoteFilePath.replace(“\\”, “/”); }
String remoteFileName = “”;
// 대상폴더 이동 int lastSlashIndex = remoteFilePath.lastIndexOf(“/”); if (lastSlashIndex > -1) { String cdDir = remoteFilePath.substring(0, lastSlashIndex); remoteFileName = remoteFilePath.substring(lastSlashIndex + 1); channelSftp.cd(cdDir); } else { remoteFileName = remoteFilePath; channelSftp.cd(“/”); }
File destFile = new File(localDirPath + File.separator + remoteFileName); if (destFile.exists()) { if (overwrite) { destFile.delete(); } else { System.out.println(“File Download canceled. File already exists : “ + destFile.getAbsolutePath()); return false; } }
// 파일 다운로드 bis = new BufferedInputStream(channelSftp.get(remoteFileName)); fos = new FileOutputStream(destFile); bos = new BufferedOutputStream(fos); int readCount = 0; while ((readCount = bis.read(buffer)) > 0) { bos.write(buffer, 0, readCount); }
isSuccess = true; System.out.println(“File downloaded : “ + remoteFilePath + ” => “ + destFile.getAbsolutePath());
} catch (Exception e) { throw e;
} finally { close(bos); close(fos); close(bis); }
return isSuccess; }
/** * 폴더 생성 * * @param dirPath * @param dirName * @throws Exception */ public boolean mkdir(String dirPath, String dirName) throws Exception { boolean isSuccess = false;
String destDirPath = dirPath + “/” + dirName;
boolean destDirExists = false;
try { channelSftp.cd(destDirPath); destDirExists = true;
} catch (Exception e) { destDirExists = false; }
if (destDirExists) { System.out.println(“Folder Creation canceled. Folder already exists : “ + destDirPath); return false; }
// 대상폴더 이동 channelSftp.cd(dirPath);
// 폴더 생성 channelSftp.mkdir(dirName); isSuccess = true;
System.out.println(“Folder created : “ + destDirPath); return isSuccess; }
/** * SFTP 접속하기 * * @return * @throws JSchException * @throws Exception */ public void connectSFTP(String host, int port, String userName, String password) throws Exception { // JSch 객체를 생성 JSch jsch = new JSch();
// JSch 세션 객체를 생성 (사용자 이름, 접속할 호스트, 포트 전달) jschSession = jsch.getSession(userName, host, port);
// 패스워드 설정 jschSession.setPassword(password);
// 기타설정 적용 Properties config = new Properties(); config.put(“StrictHostKeyChecking”, “no”); jschSession.setConfig(config);
// 접속 jschSession.connect();
// sftp 채널 열기 channel = jschSession.openChannel(“sftp”);
// sftp 채널 연결 channelSftp = (ChannelSftp) channel; channelSftp.connect(); }
/** * SFTP 접속해제 */ public void disconnectSFTP() { try { if (channelSftp != null && channelSftp.isConnected()) { channelSftp.disconnect(); } } catch (Exception e) { } finally { channelSftp = null; }
try { if (channel != null && channel.isConnected()) { channel.disconnect(); } } catch (Exception e) { } finally { channel = null; }
try { if (jschSession != null && jschSession.isConnected()) { jschSession.disconnect(); } } catch (Exception e) { } finally { jschSession = null; } }
/** * FileInputStream 객체 닫기 * * @param fis */ private void close(FileInputStream fis) { try { if (fis != null) { fis.close(); } } catch (Exception e) { } finally { fis = null; } }
/** * BufferedInputStream 객체 닫기 * * @param bis */ private void close(BufferedInputStream bis) { try { if (bis != null) { bis.close(); } } catch (Exception e) { } finally { bis = null; } }
/** * FileOutputStream 객체 닫기 * * @param fos */ private void close(FileOutputStream fos) {
try { if (fos != null) { fos.flush(); } } catch (Exception e) { }
try { if (fos != null) { fos.close(); } } catch (Exception e) { } finally { fos = null; } }
/** * BufferedOutputStream 객체 닫기 * * @param bos */ private void close(BufferedOutputStream bos) {
try { if (bos != null) { bos.flush(); } } catch (Exception e) { }
try { if (bos != null) { bos.close(); } } catch (Exception e) { } finally { bos = null; } } }
|
위와 같이 JSchWrapper 라는 클래스를 만들어뒀기 때문에 실제 사용은 간편하다.
아래는 SFTP 접속, 폴더 생성, 파일 업로드, 파일 다운로드, SFTP 접속해제를 하는 자바코드다.
실행하기 전에 C:\ 드라이브에 test라는 폴더를 만들고, test 폴더 안에 download 폴더와 upload 폴더를 만든다.
(C:\test\download 폴더 생성, C:\test\upload 폴더 생성)
그리고 C:\test\upload 폴더 안에 임의의 그림파일을 만들고 파일명을 0001.png 이라고 정한다.
(C:\test\upload\0001.png 그림파일 준비)
이후 아래 코드를 실행했을 때 C:\test\download 폴더 안에 0001.png 파일이 다운로드 받아지면 성공이다.
|
public class TestClass {
public static void main(String[] args) { JSchWrapper jschWrapper = null;
try { jschWrapper = new JSchWrapper();
// SFTP 접속하기 (주소, 포트번호, 사용자아이디, 패스워드) jschWrapper.connectSFTP(“itarchives.cafe24.com”, 22, “username”, “1234”);
// /itarchives 폴더 위치에 test 폴더 생성 jschWrapper.mkdir(“/itarchives”, “test”);
// C:\\test\\upload\\0001.png 파일을 /itarchives/test 위치에 업로드 jschWrapper.uploadFile(“C:\\test\\upload\\0001.png”, “/itarchives/test”);
// /itarchives/test/0001.png 파일을 C:\\test\\download 위치에 다운로드 jschWrapper.downloadFile(“/itarchives/test/0001.png”, “C:\\test\\download”, false);
} catch (Exception e) { e.printStackTrace();
} finally { // SFTP 접속해제 jschWrapper.disconnectSFTP(); } } }
|
실행결과
|
Folder created : /itarchives/test
File uploaded : C:\test\upload\0001.png => /itarchives/test/0001.png
File downloaded : /itarchives/test/0001.png => C:\test\download\0001.png
|
참고사이트 : https://steemit.com/kr-dev/@capslock/java-sftp-using-jsch-sftp