Feat: 파일 전송 기능 구현 (업로드/다운로드)
- RETR 명령어 구현: 파일 다운로드 * 파일 존재 여부 확인 * 데이터 연결을 통한 파일 스트림 전송 * 전송 바이트 수 로깅 * 에러 처리 및 연결 자동 종료 - STOR 명령어 구현: 파일 업로드 * 현재 디렉토리에 파일 생성 * 데이터 연결을 통한 파일 스트림 수신 * 전송 완료 후 파일 크기 확인 * 에러 처리 및 연결 자동 종료 - 두 명령어 모두 PASV 선행 필수 - FileInputStream/FileOutputStream을 사용한 스트림 처리 - 전송 성공/실패에 따른 적절한 응답 코드 반환 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -107,6 +107,12 @@ public class FTPSession implements Runnable {
|
||||
case "PASV":
|
||||
handlePasv();
|
||||
break;
|
||||
case "RETR":
|
||||
handleRetr(argument);
|
||||
break;
|
||||
case "STOR":
|
||||
handleStor(argument);
|
||||
break;
|
||||
case "NOOP":
|
||||
handleNoop();
|
||||
break;
|
||||
@@ -369,6 +375,104 @@ public class FTPSession implements Runnable {
|
||||
}
|
||||
}
|
||||
|
||||
private void handleRetr(String fileName) throws IOException {
|
||||
if (!isAuthenticated) {
|
||||
sendResponse(FTPResponse.NOT_LOGGED_IN, "Please login first");
|
||||
return;
|
||||
}
|
||||
|
||||
if (fileName.isEmpty()) {
|
||||
sendResponse(FTPResponse.SYNTAX_ERROR_PARAMETERS, "No file name specified");
|
||||
return;
|
||||
}
|
||||
|
||||
if (dataConnection == null) {
|
||||
sendResponse(FTPResponse.CANNOT_OPEN_DATA_CONNECTION, "Use PASV first");
|
||||
return;
|
||||
}
|
||||
|
||||
java.io.File file = fileSystem.getFile(fileName);
|
||||
if (file == null || !file.exists() || !file.isFile()) {
|
||||
sendResponse(FTPResponse.FILE_UNAVAILABLE, "File not found");
|
||||
dataConnection.close();
|
||||
dataConnection = null;
|
||||
return;
|
||||
}
|
||||
|
||||
sendResponse(FTPResponse.FILE_STATUS_OK, "Opening data connection for " + fileName + " (" + file.length() + " bytes)");
|
||||
|
||||
if (dataConnection.acceptConnection()) {
|
||||
try {
|
||||
java.io.FileInputStream fis = new java.io.FileInputStream(file);
|
||||
if (dataConnection.transferStream(fis)) {
|
||||
fis.close();
|
||||
dataConnection.close();
|
||||
sendResponse(FTPResponse.CLOSING_DATA_CONNECTION, "Transfer complete");
|
||||
Log.i(TAG, "File sent: " + fileName + " (" + file.length() + " bytes)");
|
||||
} else {
|
||||
fis.close();
|
||||
dataConnection.close();
|
||||
sendResponse(FTPResponse.CONNECTION_CLOSED, "Transfer failed");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Error sending file: " + e.getMessage());
|
||||
dataConnection.close();
|
||||
sendResponse(FTPResponse.CONNECTION_CLOSED, "Transfer error: " + e.getMessage());
|
||||
}
|
||||
} else {
|
||||
dataConnection.close();
|
||||
sendResponse(FTPResponse.CANNOT_OPEN_DATA_CONNECTION, "Cannot open data connection");
|
||||
}
|
||||
|
||||
dataConnection = null;
|
||||
}
|
||||
|
||||
private void handleStor(String fileName) throws IOException {
|
||||
if (!isAuthenticated) {
|
||||
sendResponse(FTPResponse.NOT_LOGGED_IN, "Please login first");
|
||||
return;
|
||||
}
|
||||
|
||||
if (fileName.isEmpty()) {
|
||||
sendResponse(FTPResponse.SYNTAX_ERROR_PARAMETERS, "No file name specified");
|
||||
return;
|
||||
}
|
||||
|
||||
if (dataConnection == null) {
|
||||
sendResponse(FTPResponse.CANNOT_OPEN_DATA_CONNECTION, "Use PASV first");
|
||||
return;
|
||||
}
|
||||
|
||||
java.io.File file = new java.io.File(fileSystem.getCurrentDirectory(), fileName);
|
||||
|
||||
sendResponse(FTPResponse.FILE_STATUS_OK, "Opening data connection for " + fileName);
|
||||
|
||||
if (dataConnection.acceptConnection()) {
|
||||
try {
|
||||
java.io.FileOutputStream fos = new java.io.FileOutputStream(file);
|
||||
if (dataConnection.receiveStream(fos)) {
|
||||
fos.close();
|
||||
dataConnection.close();
|
||||
sendResponse(FTPResponse.CLOSING_DATA_CONNECTION, "Transfer complete");
|
||||
Log.i(TAG, "File received: " + fileName + " (" + file.length() + " bytes)");
|
||||
} else {
|
||||
fos.close();
|
||||
dataConnection.close();
|
||||
sendResponse(FTPResponse.CONNECTION_CLOSED, "Transfer failed");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Error receiving file: " + e.getMessage());
|
||||
dataConnection.close();
|
||||
sendResponse(FTPResponse.CONNECTION_CLOSED, "Transfer error: " + e.getMessage());
|
||||
}
|
||||
} else {
|
||||
dataConnection.close();
|
||||
sendResponse(FTPResponse.CANNOT_OPEN_DATA_CONNECTION, "Cannot open data connection");
|
||||
}
|
||||
|
||||
dataConnection = null;
|
||||
}
|
||||
|
||||
private void handleNoop() throws IOException {
|
||||
sendResponse(FTPResponse.COMMAND_OK, "OK");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user