프로그래밍 공부

2025.03.14 스프링 공부

3452 2025. 3. 14. 17:46

파일 업로드

 

MultipartFile 인터페이스를 이용해서 파일을 업로드 하기 위해서 pom.xml에 라이브러리를 가져와야한다.

 

<dependency>

    <groupId>commons-fileupload</groupId>

    <artifactId>commons-fileupload</artifactId>

    <version>1.4</version>

</dependency>

 

<dependency>

    <groupId>commons-io</groupId>

    <artifactId>commons-io</artifactId>

    <version>2.11.0</version>

</dependency>

 

그 후 servlet-context.xml 파일에서 <beans:bean>태그를 이용해 객체 생성한다.

 

<beans:bean id="multipartResolver"

class="org.springframework.web.multipart.commons.CommonsMultipartResolver">

<beans:property name="maxUploadSize" value="10240000"/>

</beans:bean>

 

이러면 pom.xml에 있는 라이브러리를 생성하는데, 업로드 할 최대 파일의 크기를 1024000바이트로 제한한다.

 

멀티파트파일 타입으로 이미지를 받을 변수를 DTO에 선언하고, getter/setter 함수를 만든다.

 

private MultipartFile bookImage;

 

public MultipartFile getBookImage() {

    return bookImage;

}

 

public void setBookImage(MultipartFile bookImage) {

    this.bookImage = bookImage;

}

 

컨트롤러에서 파일을 업로드하는 함수를 수정한다.

 

@PostMapping("/add")

public String submitAddNewBook(@ModelAttribute("NewBook") Book book, HttpServletRequest req) {

MultipartFile bookImage = book.getBookImage();

//파일이름 겹치지 않게 만드는 방법

String now = String.valueOf(System.currentTimeMillis());

System.out.println("현재시간: "+now);

 

String saveName = bookImage.getOriginalFilename();

System.out.println("저장되는 파일이름: "+saveName);

 

String[] format = saveName.split("\\.");

for(int i=0; i<format.length;i++) {

System.out.println(format[i]);

}

 

String newFileName = now+"."+format[1];

System.out.println(newFileName);

//-----------------------------------------------------

 

String path = req.getRealPath("resources/images");

 

File saveFile = new File(path, newFileName);

try {

bookImage.transferTo(saveFile);

}catch (Exception e) {}

 

book.setSaveName(newFileName);

 

bookService.setNewBook(book);

System.out.println("book 내용물 : " + book.toString());

 

return "redirect:/books";

}

 

먼저 book에서 이미지의 정보들을 가져와 멀티파트파일 타입의 bookImage 변수에 담는다.

 

전달받은 이미지 파일 이름이 중복되면 안되기 때문에 이름을 설정하기 위해서 밀리초 단위의 시간을 문자열 형태로 변환해서 now 변수에 담는다.

 

bookImage에 있는 파일의 이름을 saveName 변수에 담는다.

 

파일의 확장자를 추출하기 위해서 saveName 변수를 .을 기준으로 앞 뒤로 분리한 후(파일명 . 확장자) format 배열에 담아서 for문으로 순회하여 1번 인덱스에 담기는 확장자명을 가져온다.

 

now + "." + format[1]; 을 이용해서 계속바뀌는 시간.확장자 의 형태로 파일 이름을 만들어서 newFileName 변수에 담는다.

 

req.getRealPath("resources/images")를 이용해 리소스폴더 안의 이미지폴더의 경로를 얻어와서 path 변수에 담는다.

 

위에서 만든 경로(path)와 파일명(newFileName)을 이용해서 새 파일을 만들어서 saveFile 변수에 담는다.

 

bookImage 변수에 담긴 이미지에 관한 내용들을 transferTo 함수를 이용해 saveFile 파일에 기록한다.

 

그 후 모델에 이동해서 이미지를 리파지토리에 등록한 뒤에 다시 컨트롤러로 돌아와서 books로 리다이렉트 시켜 등록된 이미지를 사용자에게 보여준다.

 


 

스프링 예외 처리

 

스프링에서 예외 처리 방법에는 @ResponseStatus, @ExceptionHandler, @ControllerAdvice가 있으며, 주로 @ExceptionHandler를 사용한다.

 

 

@ResponseStatus

 

에러가 발생할때 예외로 바꾸어주는 설정을 할 수 있는 어노테이션이지만, 예외페이지에서 서버의 프로그램과 버전을 노출시키기 때문에 보안에 취약하여 사용하지 않는다.

 


 

 

@ExceptionHandler

 

@ExceptionHandler는 컨트롤러에서 발생한 특정 예외를 처리하는 메서드를 지정할 때 사용하는 어노테이션이다.
메서드 위에 @ExceptionHandler(예외 클래스.class) 형태로 추가하여, 해당 예외가 발생했을 때 실행되도록 설정할 수 있다.
이렇게 하면 예외 발생 시 특정 예외 페이지로 이동하도록 처리할 수 있다.

 

@Controller
public class SampleController {

    @GetMapping("/test")
    public String test() {
        throw new IllegalArgumentException("잘못된 입력입니다.");
    }

    @ExceptionHandler(IllegalArgumentException.class)
    public String handleIllegalArgument(IllegalArgumentException e, Model model) {
        model.addAttribute("message", e.getMessage());
        return "error-page"; // 예외 발생 시 error-page.html로 이동
    }
}

 


 

 

@ControllerAdvice

 

프로젝트 전역에 대한 예외처리를 담당하는 어노테이션으로, @ControllerAdvice(basePackages={"com.패키지이름"})의 형태로 지정해두면 해당 패키지에서 일어나는 모든 예외에 대해서 @ControllerAdvice 어노테이션이 붙은 함수가 처리하게 된다.

 

프로젝트 전역에 대해서 처리하기 때문에 해당 지역의 예외만 처리하는 어노테이션과 겹칠수 있는데, 이 경우에는 그 지역 예외를 담당하는 어노테이션이 먼저 처리되고, 예외가 처리되지 않으면 전역 예외처리가 적용된다.

 

 

예외를 처리할 때 가장 좋은 방법은 사용자에게 아무런 정보를 주지 않고 예외처리용 JSP나 HTML파일을 만들어서 이동시키고 정상페이지로 이동하게끔 만드는것이 보안상의 문제가 생기지 않아 가장 좋다.