티스토리 뷰
* 개요
org.apache.commons.net.ftp.FTPClient
* FTPClient#enterLocalPassiveMode()
- FTP 의 액티브 모드와 패시브 모드에 대해서 알아야 함
https://extrememanual.net/3504
- 액티브 모드 : 클라이언트가 서버에 데이터 전송 요청하면
서버가 클라이언트에 접속해 파일을 올려줌
- 패시브 모드 : 클라이언트가 서버로부터 데이터를 내려받음
- 액티브 모드일때는 클라이언트가 정해준 특정 포트로 서버가 데이터를 전송해주는 것이므로
클라이언트에 방화벽이 있다면 서버가 접근할 수 없음.
* 인코딩 문제
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() 안해서 그랬던 경우가 있었음)
- 그 이후 접속에 대해서 한동안 500 뱉어내는 문제가 있었음.
윈도우즈 CMD> netstat
에서 연결된 것 찾아서 끊으면 되지 않을까 싶었지만 시도해보지 않음.
http://www.massapi.com/method/org/apache/commons/net/ftp/FTPClient.completePendingCommand.html
'SW개발 > Java' 카테고리의 다른 글
Properties 위치 / java.io.IOException: java.io.FileNotFoundException: XXXX.properties (지정된 파일을 찾을 수 없습니다) (0) | 2019.06.06 |
---|---|
java.lang.ClassFormatError: Truncated class file (0) | 2019.02.25 |
자바 인코딩 관련 문제 종합 정리 (1) | 2019.02.13 |
FTPClient storeFile 실패 (0) | 2019.02.13 |
FTPClient NullPointerException (0) | 2019.02.13 |