mj@home:~$

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();