[이미지 업로드 기능] 만들기
엔시티 멤버 등록시 이미지 파일을 첨부하여 업로드하고 > 이것을 저장한 디렉토리를 DB에 저장하기로 하였다.
1) DB TABLE은 이렇게 생성했다.
CREATE TABLE nctmembers (
id NUMBER PRIMARY KEY,
name VARCHAR2(255),
birthdate DATE,
nationality VARCHAR2(255) NOT NULL,
position VARCHAR2(200) NOT NULL,
mbti VARCHAR2(4),
image VARCHAR2(100) NOT NULL,
regdate DATE DEFAULT SYSDATE
);
2) 프론트의 <form action> 을 살짝 수정한다.
<form action="${ctxPath}/admin/memberRegister" method="post"> 를
<form action="${ctxPath}/admin/memberRegister" method="post" enctype="multipart/form-data">
로 수정하기.
enctype = "multipart/form-data" 를 사용하면 >> 폼의 입력 데이터 (input fields)와 함께 파일 데이터도 서버로 전송된다.
폼 내의 여러 입력 데이터와 파일을 함께 전송할 때 enctype="multipart/form-data"는 필수적이다.
그리고 이미지 파일 받아오는 구조는 요렇게 구성했다.
<!-- 이미지 파일 등록 -->
<div class="form-group row">
<label for="image" class="col-sm-3 col-form-label text-nowrap">이미지파일 등록</label>
<div class="col-sm-9">
<input type="file" class="form-control text-right" id="file" name="file">
</div>
</div>
3) 컨트롤러 수정
엔시티 멤버 등록 요청을 처리하는 컨트롤러에 메서드를 만든다.
나는 /registerform에서 받아온 input 값들을 memberDTO로 넘겨주는 메소드이자 이미지 파일 정보도 같이 연결하는 메소드를 만들었다.
@param file - 관리자가 업로드한 파일
@param dto - 관리자가 입력한 엔시티 멤버 정보
@param request - HttpServletRequest 객체
@param model - Model 객체
@return String >> 리다이렉션 url
@throws Exception >>예외 처리
@RequestMapping("/nctregister")
public String memberRegister(@RequestParam("file") MultipartFile file, @ModelAttribute NCTmemberDTO dto, HttpServletRequest request, Model model) throws Exception {
// 파일을 업로드할 디렉토리 경로 설정
String UPLOAD_DIR = "resources/file_repo";
// 웹어플리케이션상의 절대경로를 구할수 있다.
ServletContext servletContext = request.getSession().getServletContext();
/*
* 톰캣을 포함한 많은 웹 서버는 웹 애플리케이션을 실행할 때 원본 프로젝트의 위치가 아닌
다른 임시 디렉터리에 애플리케이션을 배포하여 실행한다.
servletContext.getRealPath("")를 사용하면, 그 임시 디렉터리 내의 애플리케이션 루트 경로를 얻게 된다.
이렇게 임시 디렉터리에 저장된 파일들은 IDE의 프로젝트 구조 내에서는 직접적으로 보이지 않음.
만약 웹 애플리케이션을 다시 시작하거나 재배포할 경우, 이 임시 디렉터리의 내용은 리셋됨.
*/
String uploadPath = servletContext.getRealPath("") + File.separator + UPLOAD_DIR;
// 파일이 비어 있지 않은 경우 파일 업로드 처리하겠다.
if (!file.isEmpty()) {
// adminService의 uploadFile 메소드에 file과 uploadPath 가져옴.
File uploadedFile = adminService.uploadFile(file, uploadPath);
System.out.println("저장소 : " + uploadPath);
// 업로드된 파일의 이름을 가져와서 이것을 dto의 이미지로 설정함.
dto.setImage(uploadedFile.getName());
System.out.println("테스트완료");
}
// 회원 등록 후 메인 페이지로 리다이렉션
return "redirect:main";
}
4) 컨트롤러 memberRegister 메소드 안에서의 서비스 내용을 또 만들어줘야 한다. >> adminService에서의 uploadFile 메소드!!!
** 일단 서비스 클래스 안에 상수를 설정해준다. 이미지 파일은 확장자와 파일 크기를 제한해줘야 하기 때문에~
// 허용된 파일 확장자를 정의한 리스트
private static final List<String> ALLOWED_EXTENSIONS = Arrays.asList("jpg", "jpeg", "png", "gif");
// 파일 크기 제한을 정의 (예: 5MB)
private static final long MAX_FILE_SIZE = 5 * 1024 * 1024;
그리고 서비스 클래스 안의 메소드를 만들어본다.
위의 컨트롤러에서 보면 파일의 임시 디렉터리의 저장 경로를 파악하고 난 후
~~
그것을 uploadPath에 저장해둔 상태.
~~
에서 파일이 비어있지 않은 경우 서비스단의 uploadFile 메서드를 실행시킨다.!!
이때 어떤 서비스가 이루어지느냐~~~ > 파일이름을 갖고와서 >> 파일의 확장자를 확인해보고(getFileExtension 메소드 활용) >>
+ 파일의 크기도 확인해본다(file.getSize()) .
그리고 업로드 디렉토리를 생성해준다. (이미 존재하지 않을 경우에만)
그리고 그 디렉토리를 봤을 때 같은 파일 이름의 파일이 있으면 새로운(랜던) 이름을 생성해주어야 한다. > 그래야 겹치는 일이 없으므로!!
그렇게 모든 절차를 거치고 나서야 실제 파일을 > 지정된 디렉토리로 옮겨주면 끝...
그러고 컨트롤러 단에서 그 파일이 uploadedFile에 저장이 되어 파일의 이름이 DTO의 이미지에 지정이 된다.
/**
* 파일을 업로드하는 메서드
* @param file - 업로드할 MultipartFile
* @param uploadPath - 업로드될 경로
* @return 업로드된 파일
* @throws Exception
*/
@Override
public File uploadFile(MultipartFile file, String uploadPath) throws Exception {
String fileName = file.getOriginalFilename();
String fileExtension = getFileExtension(fileName);
// 파일 확장자를 검사하여 허용되지 않는 확장자인 경우 예외를 발생시킨다.
if (!ALLOWED_EXTENSIONS.contains(fileExtension)) {
throw new Exception("Invalid file extension. Allowed extensions are: " + ALLOWED_EXTENSIONS);
}
// 파일의 크기를 검사하여 크기 제한을 초과하는 경우 예외를 발생시킨다.
if (file.getSize() > MAX_FILE_SIZE) {
throw new Exception("File size exceeds the limit of " + MAX_FILE_SIZE / (1024 * 1024) + "MB.");
}
// 업로드 디렉토리가 존재하지 않는 경우 디렉토리를 생성한다.
File uploadDir = new File(uploadPath);
if (!uploadDir.exists()) {
uploadDir.mkdirs();
}
// 동일한 파일 이름이 존재하는 경우 UUID를 사용하여 파일 이름을 변경한다.
File uploadFile = new File(uploadPath + File.separator + fileName);
if (uploadFile.exists()) {
String uuid = UUID.randomUUID().toString(); // UUID 생성
fileName = uuid + "_" + fileName; // 파일 이름에 UUID 추가
uploadFile = new File(uploadPath + File.separator + fileName);
}
// 실제 파일을 지정된 경로로 이동 (또는 복사) 한다.
file.transferTo(uploadFile);
return uploadFile;
}
/**
* 파일 이름에서 확장자를 추출하는 메서드
* @param fileName - 확장자를 추출할 파일 이름
* @return 파일의 확장자
*/
private String getFileExtension(String fileName) {
// 파일 이름에 확장자가 없는 경우 빈 문자열을 반환
if (fileName == null || fileName.lastIndexOf(".") == -1) {
return "";
}
return fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
}
일단 요렇게 처리를 해서 이미지 파일 업로드 과정은 완성이 되었다.
그러나 아직 DB로 insert하는 과정이 완성이 안됐다!!! 그거까지 하고 추가해야지~~~~!
'Project > nct club project' 카테고리의 다른 글
[오류] 서버 인코딩 오류 (0) | 2023.10.03 |
---|---|
오류와의 싸움기 흙 흙 ㅠㅡㅠ (1) | 2023.09.20 |
3rd day of mini project (0) | 2023.09.15 |
2nd day of mini project (0) | 2023.09.14 |
1st day of mini project (0) | 2023.09.14 |