카테고리 없음

spring boot 에서 sftp 사용하기 (삽질)

스마트큐브 2021. 1. 7. 14:09

아니 찾아보면 볼수록 java 에서 sftp 를 쓰는게 이렇게 복잡하고 어려운일인가.. 싶다. 

머가 이렇게 방법이 많은지... ㅠㅠ 

일단 spring 에서 지원하고 있는 방법이 있는거 같아서 시도해보자.

내 심플한 상상으로는   IP, Id , Pass 이용하여 클라이언트 객체를 선언하고

파일 Path 를 파라메터로 받아서 Upload 했으면 좋겠는데.. 

아무래도 그 외에 sftp 프로토콜에서 지원해야하는 많은 인터페이스를 구현해야 라이브러리가 될테니 복잡해지고 있는게 아닌가 싶다. 

어쨌거나 난 그냥 단순히 업로드만 되면 OK 인 상황이니 최대한 간단하게 해보자 

일단 젤 잘 설명되어있는것 같은 사이트로 트라이 시작! 

blog.pavelsklenar.com/spring-integration-sftp-upload-example/

 

Spring Integration: SFTP Upload Example using Key-Based Authentication

How to use Spring Integration to upload any file to a remote SFTP server using key-based or password authentication mechanism.

blog.pavelsklenar.com

# 현재 Gradle 프로젝트에서 사용하는 boot 버전 

'org.springframework.boot' version '2.1.17.RELEASE'

mvnrepository.com/ 에서 

1. 이거에 맞는 버전을 찾아보니 5.1.13 인거 같아서  build.gradle 에 추가

compile group: 'org.springframework.integration', name: 'spring-integration-sftp', version: '5.1.13.RELEASE'

 

2. 이제 환경설정 

config/SftpConfig.java 에 파일 추가

그리고 junit 클래스 로 테스트 

package com.crizen.util;

import static org.junit.Assert.assertEquals;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.stream.Collectors;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringRunner;

import com.crizen.config.SftpConfig.UploadGateway;

@RunWith(SpringRunner.class)
@SpringBootTest
@TestPropertySource(locations = "classpath:/test.yml")
public class SftpTest {

	@Autowired
    private UploadGateway gateway;
	
	private static Path sftpFolder;
	  
    @Test
    public void testUpload() throws IOException {
        // Prepare phase
        Path tempFile = Files.createTempFile("UPLOAD_TEST", ".csv");
        // test phase
        gateway.upload(tempFile.toFile());
      
    }
}

 

음 일단 동작은 한다. 하지만 먼가 복잡하다. 난 Util 처럼 이용하고 싶다.  로그를 보니  결국 jscsh 라이브러리를 사용하는 것으로 보인다.  그럼 굳이... 복잡하게 쓸 이유가 없을것 같다.  

======================================================================
다시 검색 시작 

www.programmersought.com/article/63481170477/

 

SpringBoot + SFTP implements file upload and download - Programmer Sought

background Recently, I need to upload and download files at work. I originally planned to use some advanced file systems, such as FastDFS, GlusterFS, and CephFS. These advanced file storage systems, of course, the blogger also spent two weeks to do this. T

www.programmersought.com

  오 이게 심플해 보인다. 

 

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;

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 SftpUtil {
 
    // Set the prompt when logging in for the first time. Optional value: (ask | yes | no)
    private static final String SESSION_CONFIG_STRICT_HOST_KEY_CHECKING = "StrictHostKeyChecking";
 
    String host ="";
    String username ="";
    String password = "";
    String root = "/home/";
    
    int port = 22;
    int timeout = 15000;
    
    public SftpUtil(String host , String username , String password)
    {
    	this.host = host;
    	this.username = username;
    	this.password = password;
    }
    
	private ChannelSftp createSftp() throws Exception {
		JSch jsch = new JSch();


		Session session = createSession(jsch, host, username, port);
		session.setPassword(password);
		session.connect(timeout);



		Channel channel = session.openChannel("sftp");
		channel.connect(timeout);

		return (ChannelSftp) channel;
	}

	 

	
    private Session createSession(JSch jsch, String host, String username, Integer port) throws Exception {
        Session session = null;
 
        if (port <= 0) {
            session = jsch.getSession(username, host);
        } else {
            session = jsch.getSession(username, host, port);
        }
 
        if (session == null) {
            throw new Exception(host + " session is null");
        }
 
        session.setConfig(SESSION_CONFIG_STRICT_HOST_KEY_CHECKING, "no");
        return session;
    }

    private void disconnect(ChannelSftp sftp) {
        try {
            if (sftp != null) {
                if (sftp.isConnected()) {
                    sftp.disconnect();
                } else if (sftp.isClosed()) {
                }
                if (null != sftp.getSession()) {
                    sftp.getSession().disconnect();
                }
            }
        } catch (JSchException e) {
            e.printStackTrace();
        }
    }
    
    
    public boolean uploadFile(String targetPath, File file) throws Exception {
        return this.uploadFile(targetPath, new FileInputStream(file));
    }
    
    private boolean uploadFile(String targetPath, InputStream inputStream) throws Exception {
        ChannelSftp sftp = this.createSftp();
        try {
            sftp.cd(root);
 

            int index = targetPath.lastIndexOf("/");
 
            String fileName = targetPath.substring(index + 1);

            sftp.put(inputStream, fileName);
            return true;
        } catch (Exception e) {
        
        
            throw new Exception("Upload File failure");
        } finally {
            this.disconnect(sftp);
        }
    }
    
    
    
    public static void main(String[] args) {
		
    	SftpUtil ftp = new SftpUtil("아이피", "아이디", "비번");
    	
    	File file = new File("C:\\test.xml");
    	
    	try {
			ftp.uploadFile("/test.xml", file);
		} catch (Exception e) {			
			e.printStackTrace();
		}
    	

    
    }
    

 

오!  딱 상상하던데로이다.  잘 동작한다