[Java] FTP 서버로 파일 전송(업로드) 방법 및 다계층 디렉토리 만들기

2022. 11. 15. 11:29 JAVA/Java

[Java] FTP 서버로 파일 전송(업로드) 방법 및 다계층 디렉토리 만들기


 

1. 의존성 주입 (pom.xml)

 

<dependency>
	<groupId>commons-net</groupId>
	<artifactId>commons-net</artifactId>
	<version>3.3</version>
</dependency>

 

 

2. FTP 생성자 코드

 

import java.io.IOException;
import java.io.InputStream;

import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPReply;

public class FTPControl {
	
	private FTPClient ftpClient;
	
	public FTPControl() {
		this.ftpClient = new FTPClient();
	}
	
	// FTP 연결 및 설정
	// ip : FTP IP, port : FTP port, id : FTP login Id, pw : FTP login pw, dir : FTP Upload Path
	public void connect(String ip, int port, String id, String pw, String dir) throws Exception{
		try {
			boolean result = false;
			ftpClient.connect(ip, port);			//FTP 연결
			ftpClient.setControlEncoding("UTF-8");	//FTP 인코딩 설정
			int reply = ftpClient.getReplyCode();	//응답코드 받기
	        
			if (!FTPReply.isPositiveCompletion(reply)) {	//응답 False인 경우 연결 해제
				ftpClient.disconnect();
				throw new Exception("FTP서버 연결실패");
			}
			if(!ftpClient.login(id, pw)) {
				ftpClient.logout();
				throw new Exception("FTP서버 로그인실패");
			}
	        
			ftpClient.setSoTimeout(1000 * 10);		//Timeout 설정
			ftpClient.login(id, pw);				//FTP 로그인
			ftpClient.setFileType(FTP.BINARY_FILE_TYPE);	//파일타입설정
			ftpClient.enterLocalPassiveMode();			//Active 모드 설정
			result = ftpClient.changeWorkingDirectory(dir);	//저장파일경로

			if(!result){	// result = False 는 저장파일경로가 존재하지 않음
				ftpClient.makeDirectory(dir);	//저장파일경로 생성
				ftpClient.changeWorkingDirectory(dir);	
			}
		} catch (Exception e) {
			if(e.getMessage().indexOf("refused") != -1) {
				throw new Exception("FTP서버 연결실패");
			}
            throw e;
		}
	}

	// FTP 연결해제
	public void disconnect(){
		try {
			if(ftpClient.isConnected()){
				ftpClient.disconnect();
			}
		} catch (IOException e) {
			int a = 0; 
			int b = 0;
			a = b;
			b = a;
		}
	}

	// FTP 파일 업로드
	public void storeFile(String saveFileNm, InputStream inputStream) throws Exception{
		try {
			if(!ftpClient.storeFile(saveFileNm, inputStream)) {
				throw new Exception("FTP서버 업로드실패");
			}
		} catch (Exception e) {
			if(e.getMessage().indexOf("not open") != -1) {
				throw new Exception("FTP서버 연결실패");
			}
            throw e;
		}
	}
}

 

 

 

3. FTP 생성자 호출코드

 

파일 업로드는 로컬에 있는 File과 View에서 전송한 MultiPartFile 두 가지 방법으로 알아보겠습니다.

 

- 로컬 파일 객체 업로드

//FTP코드 생성자
FTPControl ftp = new FTPControl();
FileInputStream fis = null;

public void FtpFileUpload() {
	try {
		ftp.connect(FTP_IP, FTP_PORT, FTP_ID, FTP_PASSWORD, FTP_UPLOAD_PATH);
		String[] filenNmList = ftp.getFileNames(); 	// FTP 파일명

		String filename = "test.png";
		File file = new File("C:\\file\\test.png"); // 로컬 파일 경로
		try {    
			for(int z=0; z<list.size(); z++) {
				if(list[z].equals(filename)) {
					throw new Exception("이미 존재하는 파일명입니다.");
				}
			}

			fis = new FileInputStream(file);
			ftp.storeFile(filename, fis); 	//파일명
		} catch (Exception e) {

		} finally {
			if(fis != null) {
				fis.close();
			}
		}    
    
		ftp.disconnect();

	} catch (NumberFormatException e) {
	
	} catch (Exception e) {

	}
}

 

 

- MultipartFile 객체 업로드 

//FTP코드 생성자
FTPControl ftp = new FTPControl();
FileInputStream fis = null;

public void FtpFileUpload(List<MultipartFile> mf) {
	try {
		ftp.connect(FTP_IP, FTP_PORT, FTP_ID, FTP_PASSWORD, FTP_UPLOAD_PATH);
		String[] filenNmList = ftp.getFileNames(); 	// FTP 파일명
    
		try {    
			String filename = null;
			// 멀티파일 개수만큼 파일명 체크 후 업로드
			for(int i=0; i<mf.size(); i++) {
				filename = mf.get(i).getOriginalFilename();
				for(int z=0; z<list.size(); z++) {
					if(list[z].equals(filename)) {
						throw new Exception("이미 존재하는 파일명입니다.");
					}
				}
				
				// MultipartFile to FileInputStream
				File f = new File(mf.get(i).getOriginalFilename());	
				mf.get(i).transto(f);
				fis = new FileInputStream(f);
				ftp.storeFile(filename, fis); 	//파일명
			} 
		} catch (Exception e) {

		} finally {
			if(fis != null) {
				fis.close();
			}
		}    
    
		ftp.disconnect();

	} catch (NumberFormatException e) {
	
	} catch (Exception e) {

	}
}

 

 

 

 

4. FTPClient 다계층 디렉토리 만들기 오류

 

만약 저장파일 경로가 FTP 루트경로가 아니고 여러 하위경로가 있는 경로일 경우, Exception도 발생하지 않고 설정한 경로가 아닌 FTP 루트 경로에 업로드될 때가 있다.

 

경로가 없어서 makeDirectory를 호출할 때, 생성하려는 경로가 하위경로가 있다면 존재하지 않는 상위경로부터 만들어줘야한다.

 

FTP 생성자 코드를 보면 result가 false일 때 디렉토리 생성하는 부분이있다.

 

	result = ftpClient.changeWorkingDirectory(저장경로파일);

	// 디렉토리 만드는 부분
	if(!result){
		ftpClient.makeDirectory(저장경로파일);
		ftpClient.changeWorkingDirectory(저장경로파일);
	}

 

이때 설정 경로에 하위경로가 없거나, 고정으로 디렉토리를 사용한다면 위의 코드면 충분하지만 그렇지 않을 경우에는

상위경로부터 만들어주는 과정이 필요하다.

 

 

	result = ftpClient.changeWorkingDirectory(저장경로파일);

	// 디렉토리 만드는 부분
	if(!result){
		boolean result = false;
		String[] directory = dir.split("/");
		
		String newdir = "";
		for(int i=0, l=directory.length; i<l; i++) {
			newdir += ("/" + directory[i]);
			try {
				result = ftpClient.changeWorkingDirectory(newdir);
				if(!result) {
		        	ftpClient.makeDirectory(newdir);
		        	ftpClient.changeWorkingDirectory(newdir);
				}
			} catch (IOException e) {
				throw e;
			}
		}
	}

 

출처 : https://haenny.tistory.com/259