[이미지 업로드 기능] 만들기

2023. 9. 19. 15:20
728x90

 

엔시티 멤버 등록시 이미지 파일을 첨부하여 업로드하고 > 이것을 저장한 디렉토리를 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하는 과정이 완성이 안됐다!!! 그거까지 하고 추가해야지~~~~!

728x90

'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

BELATED ARTICLES

more