
개요
안녕하세요 빈코입니다. 오늘은 Java에서 FTPClient()를 활용하여 서버에 파일을 전송하는 방법에 대해 포스팅하려고 합니다. 포스팅은 Front에서부터 Back까지 전반적으로 진행하기 때문에, 만약 DB에서 파일을 꺼내오시는 분들은 Service 챕터만 확인하시면 됩니다😁
그럼 시작해 볼까요?
UI 📙

첫 번째로는 FTP 서버에 파일을 보내기 위해서는 FTP 서버 연결을 위한 4가지 정보(host, port, user, password)가 필요합니다. 그래서 UI에서 입력받도록 설정하였고, 저는 간단한 예시 작성을 위해 파일은 사용자에게 입력 받도록 구성했습니다. 코드는 아래와 같습니다.
<h4>FTP 테스트</h4>
<div>
<div style="margin-bottom:10px;">
<span style="width:150px;">FTP 서버</span>
<input class="form-control" type="text" id="ftp_host" style="width:300px;" placeholder="smtp.jiran.com"> : <input class="form-control" type="text" id="ftp_port" style="width:50px;" oninput="this.value = this.value.replace(/[^0-9]/g, '');" placeholder="25">
</div>
<div style="margin-bottom:10px;">
<span style="width:150px;">사용자명</span>
<input class="form-control" type="text" id="ftp_user_name" style="width:360px;">
</div>
<div style="margin-bottom:10px;">
<span style="width:150px;">비밀번호</span>
<input class="form-control" type="password" autocomplete="off" id="ftp_password" style="width:360px;">
</div>
<div style="margin-bottom:10px;">
<span style="width:150px;">파일 선택</span>
<input type="file" id="ftp_file">
</div>
<span style="width:150px;"></span>
<button type="button" id="btnFTPTest" class="btn btn-info btn-sm" data-placement="bottom" title="FTP Test"></button>
</div>
JavaScript 📘
필요한 값들을 입력받았으면 서버로 넘기기 위해서 js를 활용합니다. UI 챕터에서 만든 'btnFTPTest' 버튼을 클릭 시 이벤트를 추가해 줍니다. formData를 생성 후 각 정보별로 UI에서 선언한 ID 값들의 value를 가져옵니다.
$('#btnFTPTest').click( function () {
var formData = new FormData();
formData.append("host", $("input[id=ftp_host]").val());
formData.append("port", $("input[id=ftp_port]").val());
formData.append("user_name", $("input[id=ftp_user_name]").val());
formData.append("password",$("input[id=ftp_password]").val());
formData.append("file", $("input[id=ftp_file]")[0].files[0]);
$.ajax({
type : "POST",
async : true,
url : "ftp/test.do",
processData: false,
contentType: false,
cache : false,
data : formData,
success:function(response, result){
if(response.result == -2) {
$.notify({
icon: 'fa fa-exclamation-triangle',
message: '로그인 실패'
});
}else if(response.result == -3) {
$.notify({
icon: 'fa fa-exclamation-triangle',
message: '잘못 된 포트 번호'
});
}else if(response.result == -4) {
$.notify({
icon: 'fa fa-exclamation-triangle',
message: 'FTP 연결 실패'
});
}else if (response.result == -1) {
$.notify({
icon: 'fa fa-exclamation-triangle',
message: '파일 업로드 실패'
});
}else {
$.notify({
icon: 'fa fa-check',
message: '파일 업로드 성공'
},{
type:"success"
});
}
}
})
});
여기서 ajax의 success의 안의 result 숫자 값들은 제가 service 단에서 임의로 명시한 것입니다. 더 자세한 내용은 service 챕터에서 확인해 볼게요😊
Controller 📒
Controller단에서는 넘겨주는 역할만 할 뿐 비즈니스 로직은 모두 Service단에서 해야 하는 거 아시죠!?
@PostMapping(value = "ftp/test.do")
public ResponseEntity<String> jsonFTPTest(@RequestParam Map<String, String> paramMap,HttpServletRequest request) {
JSONObject json = new JSONObject();
int result = settingsService.setFTPTest(paramMap, request);
json.put("result", result);
return JSONResponseUtil.getJSONResponse(json);
}
Service 📗
Service 챕터를 설명하기 전에 Java에서 FTPClient를 사용하려면 pom.xml에 라이브러리를 등록해줘야 합니다
<!-- Commons-net -->
<dependency>
<groupId>commons-net</groupId>
<artifactId>commons-net</artifactId>
<version>3.8.0</version>
</dependency>
Service단의 시나리오는 아래와 같습니다.
1. FTPClient 생성
2. UI에서부터 넘어온 file을 MultipartHttpServletRequest를 활용하여 MultipartFile 변수에 주입
3. FTP 연결 (ftpClient.connect 부분)
4. FTP 로그인 (ftpClient.login 부분)
5. FTP 업로드 위치 설정(필수 요소는 아님) - 저자는 해당 위치의 디렉터리가 없을 경우 만들고 해당 위치로 업로드하게 변경
6. 한글 제목 파일이 깨지지 않기 위해서 인코딩 설정
7. 파일 업로드 진행
8. 파일 업로드 완료 후 FTPClient 연결 종료
// logger는 slf4j의 LoggerFactory 사용 !
public int setFTPTest(Map<String, String> paramMap, HttpServletRequest request) {
FTPClient ftpClient = new FTPClient();
MultipartHttpServletRequest multipartHttpServletRequest = (MultipartHttpServletRequest) request;
MultipartFile multipartFile = multipartHttpServletRequest.getFile("file");
int result = 0;
try {
try {
ftpClient.connect(paramMap.get("host"),Integer.parseInt(paramMap.get("port")));
} catch (NumberFormatException nfe) {
logger.error("ERROR at FTP port - port({})", paramMap.get("port"));
return -3;
} catch (IOException ioe) {
logger.error("ERROR at FTP connect - msg({})", ioe.getMessage());
return -4;
}
if(!ftpClient.login(paramMap.get("user_name"), paramMap.get("password"))) {
logger.error("ERROR at FTP login - user_name({})", paramMap.get("user_name"));
return -2;
}
if (!ftpClient.changeWorkingDirectory("/upload/test")) {
ftpClient.makeDirectory("/upload/test");
ftpClient.changeWorkingDirectory("/upload/test");
}
// ftpClient.enterLocalPassiveMode(); - 추가 포트 열어야함 40000 ~ 50000
ftpClient.setControlEncoding("UTF-8");
ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
try (InputStream inputStream = multipartFile.getInputStream()) {
String fileName = new String(multipartFile.getOriginalFilename().getBytes(StandardCharsets.UTF_8), "ISO-8859-1");
boolean uploaded = ftpClient.storeFile(fileName, inputStream);
if(!uploaded) {
logger.error("ERROR at uploaded - fileName({})", multipartFile.getOriginalFilename());
return -1;
}
}
} catch (IOException e) {
logger.error(e.toString(),e);
} finally {
try {
if (ftpClient.isConnected()) {
ftpClient.logout();
ftpClient.disconnect();
}
} catch (IOException ignored) {}
}
return result;
}
모든 일련의 과정을 마치면 아래와 같이 서버에 파일이 업로드된 걸 확인할 수 있습니다😃

마치며
지금까지 Java에서 FTP를 활용하여 서버에 파일을 전송하는 방법에 대해 알아보았습니다. 예시는 간단하게 작성하였지만, 프로그램이 실행 도중에 꺼지지 않게 하기 위해서 많은 예외 처리가 필요합니다. 각 상황에 맞게 예외처리 구성하면 좋을 것 같네요🙇♂️
'TIL' 카테고리의 다른 글
Java 파일 다운로드 OutOfMemoryError 해결방법(전체 예시) (0) | 2025.01.11 |
---|---|
Java 파일 다운로드 OutOfMemoryError 해결방법(예시) (0) | 2024.12.31 |
Java 이미지 파일 다운로드 기능 구현하기(예제 포함) (1) | 2024.12.27 |
js 드래그 앤 드롭(drag&drop) 사용하기 (0) | 2024.12.18 |
Java Integer와 int 차이로 인한 오류 방지 (실무 예제) (2) | 2024.12.14 |