SpringBoot에 FTP Server, Client 구현

공부는 혼자하는 거·2021년 9월 3일
0

Spring Tip

목록 보기
7/52

두 개의 부트 앱이 있다. 하나는 client 구현, 하나는 server를 구현해서 파일을 전송해보자.

일단 클라이언트 측 작업 먼저

FTP Client 구축

		<!-- https://mvnrepository.com/artifact/commons-net/commons-net -->
		<dependency>
			<groupId>commons-net</groupId>
			<artifactId>commons-net</artifactId>
			<version>3.6</version>
		</dependency>



		<!-- https://mvnrepository.com/artifact/org.springframework.integration/spring-integration-ftp  -->
		<dependency> //요거는 필요없을 수도 있겠다.
			<groupId>org.springframework.integration</groupId>
			<artifactId>spring-integration-ftp</artifactId>
			<version>2.0.4.RELEASE</version>
		</dependency>


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

import javax.annotation.PostConstruct;

import org.apache.commons.net.PrintCommandListener;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPReply;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;



public class FTPUploader { //매번 new 하는 것보다는,

	FTPClient ftpClient = null;

	private static final Logger log = LoggerFactory.getLogger(FTPUploader.class);
	
	// param( host server ip, username, password ) 생성자
	public FTPUploader(String host, String user, String pwd) throws Exception {
		
		//log.debug("싱글톤으로 박을 수 없나.");
		ftpClient = new FTPClient();
		ftpClient.setDefaultPort(2121);
		ftpClient.addProtocolCommandListener(new PrintCommandListener(new PrintWriter(System.out)));
		int reply;
		ftpClient.connect(host);// 호스트 연결
		reply = ftpClient.getReplyCode();
		if (!FTPReply.isPositiveCompletion(reply)) {
			ftpClient.disconnect();
			throw new Exception("Exception in connecting to FTP Server");
		}
		ftpClient.login(user, pwd);// 로그인
		ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
		ftpClient.enterLocalPassiveMode();
	}

	// param( 보낼파일경로+파일명, 호스트에서 받을 파일 이름, 호스트 디렉토리 )
	public void uploadFile(String localFileFullName, String fileName, String hostDir) throws Exception {
		try (InputStream input = new FileInputStream(new File(localFileFullName))) {
			this.ftpClient.storeFile(hostDir + fileName, input);
			// storeFile() 메소드가 전송하는 메소드
		}
	}

	public void disconnect() {
		if (this.ftpClient.isConnected()) {
			try {
				this.ftpClient.logout();
				this.ftpClient.disconnect();
			} catch (IOException f) {
				f.printStackTrace();
			}
		}
	}


}

비동기 서비스 생성

소켓으로 filePath를 C:\test\CsFTPSendText.txt 요런 식으로 쏴줄거다.


	@Async
	public void ftpSendToCs2(String filePath) throws Exception { // Central Statino sever로 파일 전송
		 FTPUploader ftpUploader = new FTPUploader("localhost", "kyu",
		 "1234"); 

		logger.debug("filePath: " + filePath);
		File fileTest = new File(filePath);
		String fileName = fileTest.getName();
		logger.debug("simpleFileName: " + fileName);
		
		logger.debug("FTP SEND START");
		//ftpUploader.uploadFile(filename, "CsFTPSendText.txt", "C:" + File.separator + "kangminkyu" +  File.separator  + "aaaaaaa" + File.separator);
		ftpUploader.uploadFile(filePath, fileName, File.separator); //파일 전송시 공백있는 이름의 파일을 전송하면 안 됨, 위에서 이미 공백을 다 제거했기 때문.
		ftpUploader.disconnect();
		logger.debug("FTP SEND DONE");
		

	}

FTP Server 구축

		<!-- https://mvnrepository.com/artifact/commons-net/commons-net -->
		<dependency>
			<groupId>commons-net</groupId>
			<artifactId>commons-net</artifactId>
			<version>3.6</version>
		</dependency>



		<dependency>
			<groupId>org.apache.ftpserver</groupId>
			<artifactId>ftpserver-core</artifactId>
			<version>1.0.6</version>
		</dependency>


package net.lunalabs.central.config.ftp;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import javax.annotation.PostConstruct;

import org.apache.ftpserver.FtpServer;
import org.apache.ftpserver.FtpServerFactory;
import org.apache.ftpserver.ftplet.Authority;
import org.apache.ftpserver.ftplet.FtpException;
import org.apache.ftpserver.ftplet.FtpReply;
import org.apache.ftpserver.ftplet.FtpRequest;
import org.apache.ftpserver.ftplet.FtpSession;
import org.apache.ftpserver.ftplet.Ftplet;
import org.apache.ftpserver.ftplet.FtpletContext;
import org.apache.ftpserver.ftplet.FtpletResult;
import org.apache.ftpserver.ftplet.UserManager;
import org.apache.ftpserver.listener.ListenerFactory;
import org.apache.ftpserver.usermanager.PropertiesUserManagerFactory;
import org.apache.ftpserver.usermanager.impl.BaseUser;
import org.apache.ftpserver.usermanager.impl.WritePermission;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Configuration;


import lombok.RequiredArgsConstructor;
import net.lunalabs.central.service.FtpService;

@Configuration
@RequiredArgsConstructor
public class FtpServerMain { 


	private final FtpService ftpService;	
	private static final Logger logger = LoggerFactory.getLogger(FtpServerMain.class);
	private final FtpProperties ftpProperties;
	
	
	@PostConstruct
	public void ftpServerStart(){
		
		FtpServerFactory serverFactory = new FtpServerFactory();
		ListenerFactory factory = new ListenerFactory();
		// set the port of the listener
		factory.setPort(ftpProperties.getPort());
				
		//factory.set
		
		// replace the default listener
		serverFactory.addListener("default", factory.createListener());
		PropertiesUserManagerFactory userManagerFactory = new PropertiesUserManagerFactory();
//		userManagerFactory.setFile(new File("conf/myusers.properties"));
//		serverFactory.setUserManager(userManagerFactory.createUserManager());
				
//		String[] strAccountList = "아이디/비번,아이디/1234,아이디/1234".split(",");

		
		UserManager um = userManagerFactory.createUserManager();
		
		for(String AccountInfo : ftpProperties.getUserlist()) { //strAccountList
			
			int idx=AccountInfo.indexOf("/");
			
			String id= AccountInfo.substring(0,idx);
			String pwd= AccountInfo.substring(idx+1);
		/*	logger.trace("id=="+id+"||pw=="+pwd);*/
			
			BaseUser user = new BaseUser();
			user.setName(id);
			user.setPassword(pwd);
			user.setEnabled(true);
			
			logger.info("ftp 등록된 유저이름: " + user.getName());
			logger.info("ftp 등록된 유저패스워드: " + user.getPassword());
			
			user.setHomeDirectory(ftpProperties.getUploadDir()); //요기가 FTP server file root경로
			
			java.util.List<Authority> authorities = new java.util.ArrayList<Authority>();
	        authorities.add(new WritePermission());
			user.setAuthorities(authorities);
			
			try {
				um.save(user);
			} catch (FtpException e1) { 
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
			
		}
		
		serverFactory.setUserManager(um);
		
		Map<String, Ftplet> m = new HashMap<String, Ftplet>();
	    m.put("miaFtplet", new Ftplet()
	    {
	        @Override
	        public void init(FtpletContext ftpletContext) throws FtpException {
	            logger.info("init");
	            logger.info("Thread #" + Thread.currentThread().getId());
	            
	           
	        }

	        @Override
	        public void destroy() {
	            logger.info("destroy");
	            logger.info("Thread #" + Thread.currentThread().getId());
	        }

	        @Override
	        public FtpletResult beforeCommand(FtpSession session, FtpRequest request) throws FtpException, IOException
	        {
	            logger.info("beforeCommand " + session.getUserArgument() + " : " + session.toString() + " | " + request.getArgument() + " : " + request.getCommand() + " : " + request.getRequestLine());
	            logger.info("Thread #" + Thread.currentThread().getId());

	            //do something
	            return FtpletResult.DEFAULT;//...or return accordingly
	        }

	        @Override
	        public FtpletResult afterCommand(FtpSession session, FtpRequest request, FtpReply reply) throws FtpException, IOException
	        {
	            logger.info("afterCommand " + session.getUserArgument() + " : " + session.toString() + " | " + request.getArgument() + " : " + request.getCommand() + " : " + request.getRequestLine() + " | " + reply.getMessage() + " : " + reply.toString());
	            String strFileName = request.getArgument();
	            String strMsg = reply.getMessage();
	        	logger.info("afterCommand " + strFileName + "::::::" + strMsg);
	        	
	        	
	            if (strMsg.equals("Transfer complete.")) {
//	            if (strMsg.equals("Requested file action okay, file renamed.")) {
					
					String ip=	session.getClientAddress().getAddress().toString();
					
					try{
						
						
						ftpService.ftpFileDBSave("C:\\kangminkyu\\FTPfileUpload", strFileName); //일단은 하드코딩

					}catch(Exception e)	{
						
					}
	            }
	            
//	            logger.trace("Thread #" + Thread.currentThread().getId());

	            //do something
	            return FtpletResult.DEFAULT;//...or return accordingly
	        }

	        @Override
	        public FtpletResult onConnect(FtpSession session) throws FtpException, IOException
	        {
	            logger.info("onConnect " + session.getUserArgument() + " : " + session.toString());
	            logger.info("Thread #" + Thread.currentThread().getId());

	            //do something
	            return FtpletResult.DEFAULT;//...or return accordingly
	        }

	        @Override
	        public FtpletResult onDisconnect(FtpSession session) throws FtpException, IOException
	        {
	            logger.info("onDisconnect " + session.getUserArgument() + " : " + session.toString());
	            logger.info("Thread #" + Thread.currentThread().getId());

	            //do something
	            return FtpletResult.DEFAULT;//...or return accordingly
	        }
	        

	    });
	    serverFactory.setFtplets(m);
		// start the server
		FtpServer server = serverFactory.createServer(); 
		try {
			server.start();
		} catch (FtpException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}	}
	
	

}

profile
시간대비효율

0개의 댓글