티스토리 뷰

* 개요

org.apache.commons.net.ftp.FTPClient



* FTPClient#enterLocalPassiveMode()

- FTP 의 액티브 모드와 패시브 모드에 대해서 알아야 함

https://extrememanual.net/3504

https://idchowto.com/?p=10045


- 액티브 모드 : 클라이언트가 서버에 데이터 전송 요청하면

서버가 클라이언트에 접속해 파일을 올려줌


- 패시브 모드 : 클라이언트가 서버로부터 데이터를 내려받음


- 액티브 모드일때는 클라이언트가 정해준 특정 포트로 서버가 데이터를 전송해주는 것이므로 

클라이언트에 방화벽이 있다면 서버가 접근할 수 없음.



* 인코딩 문제

client.setControlEncoding(FTP서버 인코딩);


FTP 서버의 인코딩이 현재 내 작업환경이 아님.

파일 이름 등 한글 String 사용시 위 명령만 호출됐다면 

별도 변환 과정은 당연히 필요가 없음.


- 참고 : String 인코딩 관련

https://dogcowking.tistory.com/289




* storeFile() false 만 반환하는 경우

다음 명령을 미리 실행해서 해결할 수도...

client.enterLocalPassiveMode();

client.setFileType(FTP.BINARY_FILE_TYPE);

client.setFileTransferMode(FTP.BINARY_FILE_TYPE);

client.setControlEncoding(ftpSiteEncoding);


https://stackoverflow.com/questions/8154115/ftpclient-storefile-always-return-false



* retriveFieStream() 이 null 만 반환

상동



* storeFile 시 대상 디렉토리 문제

- 만약 "/a/b.txt" 를 업로드 한다고 가정할때 

client.storeFile("/a/b.txt", inputStream); 로는 안됨


- 먼저 작업 디렉토리 변경 과정을 거쳐야 함

client.changeWorkingDirectory("a");

client.storeFile("b.txt", inputStream);


- 디렉토리 생성시에도 마찬가지...

/a/b/c 생성한다면


1. a생성

2. a로 이동

3. b생성

4. b로 이동

5. c생성의 과정을 거쳤음.


대충 다음 코드로 사용


boolean b;


for(String tmpDir :  ftpPath.split("/") ) {

if(!tmpDir.equals("")) { // root dir 표시한경우 (/.../...) tmpDir = "" 이 되므로 건너뛰어야 함.

b = client.makeDirectory(tmpDir); // 이미 존재한다면 아무 효과 없겠다는 가정

b = client.changeWorkingDirectory(tmpDir);


}



- /a에 b.txt 를 다운받을때는 상관 없었음.

client.retrieveFileStream("/a/b.txt");





* 파일 존재하는지 여부 검사 

https://www.codejava.net/java-se/networking/ftp/determine-if-a-directory-or-file-exists-on-ftp-server


위 링크에서 다음 메서드로 FTP 서버상 파일이 존재하는지 여부를 검사함



/**
     * Determines whether a file exists or not
     * @param filePath
     * @return true if exists, false otherwise
     * @throws IOException thrown if any I/O error occurred.
     */
    boolean checkFileExists(String filePath) throws IOException {
        InputStream inputStream = ftpClient.retrieveFileStream(filePath);
        returnCode = ftpClient.getReplyCode();
        if (inputStream == null || returnCode == 550) {
            return false;
        }
        return true;
    }



- 그러나 위의 방법은 연속 실행시 오류가 있었음.

예를들어

client.retrieveFileStream(파일1);

...

client.retrieveFileStream(파일2);


을 거의 공백 없이 사용하면 

뒤에서 호출된 메서드는 false 로 작동 하는 경우가 있음.


다음과 같이 수정후 해결되었음. (이 메서드는 다양한 상황에 대해서 테스트 하지 못했음 ) 

InputStream inputStream = client.retrieveFileStream(filePath);

        

        int returnCode = client.getReplyCode();

    

    if(inputStream!=null ) {

inputStream.close();

    client.completePendingCommand();

}

    

        if (inputStream == null || returnCode == 550) {

            return false;

        }

        

        return true;




* completePendingCommand

- 이거 쓴 후 대기가 너무 길어지거나

( 이 경우는 inputStream close() 안해서 그랬던 경우가 있었음)

https://okky.kr/article/56318


- 그 이후 접속에 대해서 한동안 500 뱉어내는 문제가 있었음.

윈도우즈 CMD> netstat 

에서 연결된 것 찾아서 끊으면 되지 않을까 싶었지만 시도해보지 않음.


http://www.massapi.com/method/org/apache/commons/net/ftp/FTPClient.completePendingCommand.html

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
글 보관함