주요글: 도커 시작하기
반응형
Commons Net이 제공하는 FTPClient를 사용하여 파일을 송수신하는 방법을 살펴본다.

Jakarta Commons Net API

  • FTP, TFTP
  • SMTP, POP3
  • telnet
  • Finger, Whois, Time, Echo 등
Commons Net 라이브러리는 다양한 프로토콜에 대한 지원을 할 수 있는 구조를 갖고 있으며, 위 목록과 같이 이미 기존에 많이 사용되는 몇몇 프로토콜에 대한 클라이언트 모듈을 제공하고 있다. 또한, 개발자가 직접 프로토콜 처리를 하지 않아도 되기 때문에 관련 모듈을 빠르게 개발할 수 있는 장점도 있다.

Commons Net 라이브러리 설치하기

Commons Net 라이브러리는 http://jakarta.apache.org/commons/net 에서 다운로드 받을 수 있다. 현재 버전은 1.4.1 버전으로서, 다운로드 받은 파일의 압축을 풀면 commons-net-1.4.1.jar 파일이 생성되는데, 이 파일을 클래스패스에 추가해주면 된다.

Commons Net은 Jakarta ORO API를 필요로 한다. Jakarta ORO 관련 모듈은 http://jakarta.apache.org/oro/index.html 사이트에서 다운로드 받을 수 있다. 현재 Jakarta ORO의 버전은 2.0.8로서, 배포판의 압축을 풀면 jakarta-oro-2.0.8.jar 파일이 생성되는데 이 파일을 클래스패스에 추가해면 설치가 완료된다.

Commons Net API로 FTP 파일 송수신하기

Commons Net API는 FTP와 관련해서 다음의 두 클래스를 제공하고 있다.

  • org.apache.commons.net.ftp.FTPClient
    FTP 프로토콜 처리를 위한 API를 제공한다. 서버 연결, 로그인, 파일 목록, 송수신 등의 기능을 제공한다.
  • org.apache.commons.net.ftp.FTPFile
    FTP 서버의 파일 표현할 때 사용되는 클래스. 파일명, 파일크기, 위치 등에 대한 정보를 제공한다.
이 두 클래스만 사용하면 원격지의 FTP 서버로부터 원하는 파일을 송수신 할 수 있다. FTPClient API는 FTP 프로토콜과 관련해서 로그인, 파일 목록, 경로변경 등과 관련된 기능을 제공하는 데, 이들 기능과 관련된 메소드는 다음과 같다.

conect(Strint server, int port)
connect(String server)
FTP 서버에 접속한다. 포트 번호를 지정할 경우 해당 포트로 접속하며, 포트 번호를 지정하지 않으면 기본 포트인 21번 포트로 접속한다.
login(String user, String pass) 지정한 사용자와 암호를 사용하여 로그인한다.
changeWorkingDirectory(String path) FTP 서버에서 현재 작업 디렉토리의 경로를 변경한다.
String printWorkingDirectory() 현재 작업 디렉토리를 구한다.
FTPFile[] listFiles()
FTPFile[] listFiles(String path)
현재 작업 디렉토리에 있는 파일 목록을 구한다.
경로를 지정할 경우 해당 경로의 파일 목록을 구한다.
String[] listNames()
FTPFile[] listFiles(String path)
현재 작업 디렉토리에 있는 파일 이름을 구한다.
경로를 지정할 경우 해당 경로의 파일 이름을 구한다.
makeDirectory(String path) 새로운 디렉토리를 생성한다.
rename(String from, String to) from에 해당하는 경로를 to로 변경한다.
retriveFile(String remoteName, OutputStream local) FTP 서버의 remoteName 파일을 local에 지정된 출력 스트림에 다운로드 한다. 성공적으로 완료되면 true를 리턴한다.
InputStream retrieveFileStream(String remoteName) FTP 서버의 remoteName 파일로부터 데이터를 읽어오는 입력 스트림을 리턴한다.
storeFile(String remoteName, InputStream local) local 입력 스트림으로부터 데이터를 읽어와 FTP 서버에 remoteName 경로로 업로드한다. 성공적으로 파일을 업로드 하면 true를 리턴한다.
logout() FTP 서버에서 로그아웃한다.
disconnect() 서버와의 연결을 종료한다.

이 외에 몇가지 메소드가 더 존재하지만, 일단 위 메소드 정도만 사용하면 충분히 FTP 프로토콜을 사용해서 파일을 송수신 할 수 있게 된다.

파일 다운로드

파일을 다운로드 하기 위해서는 다음과 같은 순서로 코드를 작성하면 된다.

  1. FTPClient.connect(): FTP 서버에 접속한다.
  2. FTPClient.login(): 로그인 한다.
  3. FTPClient.changeWorkingDirectory(): 파일이 있는 폴더로 이동한다.
  4. FTPClient.retrieveFile(): 파일을 다운로드 한다.
  5. FTPClient.logout(): 로그아웃한다.
  6. FTPClient.disconnect(): 연결을 종료한다.
이를 실제 코드로 작성하면 다음과 같다.

    FTPClient ftp = null;
    try {
        ftp = new FTPClient();
        ftp.setControlEncoding("UTF-8");
        
        ftp.connect("ftp.somehost");
        ftp.login("user", "pass");
        ftp.changeWorkingDirectory("/dbdump");

        File f = new File("d:\\dbdump", "oradump1_200605.tmp");
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(f);
            boolean isSuccess = ftp.retrieveFile("oradump1.tmp", fos);
            if (isSuccess) {
                // 다운로드 성공
            } else {
                // 다운로드 실패
            }
        } catch(IOException ex) {
            System.out.println(ex.getMessage());
        } finally {
            if (fos != null) try { fos.close(); } catch(IOException ex) {}
        }
        ftp.logout();
    } catch (SocketException e) {
        System.out.println("Socket:"+e.getMessage());
    } catch (IOException e) {
        System.out.println("IO:"+e.getMessage());
    } finally {
        if (ftp != null && ftp.isConnected()) {
            try { ftp.disconnect(); } catch (IOException e) {}
        }
    }

파일 다운로드

파일 업로드는 파일을 다운로드 하는 것과 크게 다르지 않다. 차이점이 있다면 retrieveFile() 메소드 대신 storeFile() 메소드를 사용한다는 것 뿐이다. 파일 업로드 하는 예제 코드는 다음과 같다.

    FTPClient ftp = null;
    try {
        ftp = new FTPClient();
        ftp.setControlEncoding("UTF-8");
        
        ftp.connect("camp.cvnet.co.kr");
        ftp.login("uniasset", "unisise");
        ftp.changeWorkingDirectory("/dbdump");

        File uploadFile = new File("d:\\today_log.txt");
        FileInputStream fis = null;
        try {
            fis = new FileInputStream(uploadFile);
            boolean isSuccess = ftp.storeFile(uploadFile.getName(), fis);
            if (isSuccess) {
                System.out.println("업로드 성공");
            }
        } catch(IOException ex) {
            System.out.println(ex.getMessage());
        } finally {
            if (fis != null) try { fis.close(); } catch(IOException ex) {}
        }
        ftp.logout();
    } catch (SocketException e) {
        System.out.println("Socket:"+e.getMessage());
    } catch (IOException e) {
        System.out.println("IO:"+e.getMessage());
    } finally {
        if (ftp != null && ftp.isConnected()) {
            try { ftp.disconnect(); } catch (IOException e) {}
        }
    }

FTPFile 클래스

FTPClient.listFiles() 메소드를 사용하면 현재 디렉토리의 파일 및 폴더 목록을 읽어올 수 있는데, 이 때 각 파일과 폴더는 FTPFile 객체로 표현된다. FTPFile 클래스는 파일 및 폴더에 대한 정보를 제공하는데, 이와 관련된 메소드는 다음과 같다.

String getName() 파일의 이름을 구한다.
String getSize() 파일의 크기를 구한다.
boolean isDirectory() 폴더인 경우 true를 리턴한다.
boolean isFile() 파일인 경우 true를 리턴한다.
boolean isSymbolicLink() 심볼 링크인 경우 true를 리턴한다.
String getLink() 심볼 링크인 경우 링크가 가리키는 파일의 이름을 리턴한다.
Calendar getTimestamp() 생성날짜를 구한다.

이 외에도 FTPFile 클래스는 파일의 소유자 및 그룹, 권한 관련 정보를 구할 수 있는 메소드를 제공하고 있다.

결론

본 글에서는 Jakarta Commons Net API를 사용하여 FTP 파일 업로드/다운로드 기능을 구현하는 방법을 살펴봤다. Commons Net API의 FTPClient 클래스는 개발자 대신 FTP 프로토콜을 처리해줌으로써 개발자가 빠르게 FTP 관련 기능을 구현할 수 있게 해준다는 것을 알 수 있었을 것이다. FTP 뿐만 아니라 SMTP/POP3, Telnet 등 다양한 프로토콜을 처리할 수 있는 클라이언트 모듈을 제공하고 있으므로, Commons Net을 사용하면 이들 프로토콜과 관련된 클라이언트 어플리케이션을 빠르게 개발할 수 있을 것이다.

관련링크:

+ Recent posts