2016년 1월 25일 월요일

spring file uplode size 다양하게설정하기

2011년 10월에 네이버블로그에 올렸던 내용을 이곳으로 모아서 게시한다. 최근에 업무에서도 요긴하게 사용했다.

1. 요구사항
첨부파일의 크기를 업무별로 다르게 설정해야 한다. 예를 들면 일반게시판에는 20메가연계게시판에는 10메가

2. 제약사항
- Spring에서 일반적으로 사용하는 CommonsMultipartResolver에서는 maxUploadSize를 한가지만 지정할 수 있다.
제한하고자 하는 크기는 자바 클래스에 상수로 선언하여 사용해야 한다.
제한된 크기를 초과하는 경우컨트롤러 레이어에서 에러메시지나 에러페이지 등을 제어해야한다. (, Spring에서 제공하는 ExceptionResolver 등을 사용하지 않는다)

3. 해결방법
CommonsMultipartResolver를 상속하여 resolveMultipart() 메서드를 오버라이딩하여 요청 URL에 따라서 각각의 업무클래스에 정의된 maxFileSize 상수로 maxUploadSize를 설정한다.
- super.resolveMultipart(request) 메서드 처리중에 발생한 MaxUploadSizeExceededException을 잡아서 Exception 객체를 attribute로 추가한 request를 리턴하여 컨트롤러 레이어까지 처리흐름이 이어지도록 한다.
public class CustomMultipartResolver extends CommonsMultipartResolver {

        @Override
        public MultipartHttpServletRequest resolveMultipart(HttpServletRequest request) throws MultipartException {

               // 요청URL path에 따라서 결정된 세부업무별로 maxUploadSize 설정
               String url = request.getRequestURI();
               int maxFileSizeMB = 0;
              
               // 게시판
               if( url.startsWith("/au/signbbs/") ) {
                       maxFileSizeMB = AuBoardFileConstant.getMaxFileSize();
               }
               // 연계게시판
               else if( url.startsWith("/au/connect/") ) {
                       maxFileSizeMB = AuBoardFileConstant.getMaxFileSize();
               }
               else {
                       throw new MultipartException("예상치 못한 url에서 파일업로드 시도함. AuMultipartResolver.resolveMultipart()에 추가 필요");
               }
              
               setMaxUploadSize(maxFileSizeMB * 1024 * 1024);
               setMaxInMemorySize(maxFileSizeMB * 1024 * 1024);
              
               try {
                       return super.resolveMultipart(request);
               catch (MaxUploadSizeExceededException e) {
                       // 파일사이즈초과되어도 에러메시지를 위해서 request 리턴하여 컨트롤러 메서드 호출되도록 한다.
                       request.setAttribute("exception", e);
                       return new DefaultMultipartHttpServletRequest(request, new HashMap(), new HashMap());
               }
        }
}

새로 만든 MultipartResolver 클래스를 Spring 설정 xml에 CommonsMultipartResolver 대신 등록한다.
<!-- 세부업무별로 파일업로드 사이즈 제한 -->
<bean id="multipartResolver" class="common.CustomMultipartResolver" />

컨트롤러 레이어에서는 request에서 가져온 MultipartFile 객체가 null인 경우를 확인하여 예외처리를 해준다. reqeuest에 MaxUploadSizeExceededException 객체가 있다면 적당한 메시지를 생성하여 UI로 에러메시지를 보내도록 한다.
// request에서 파일을 찾아서 MultipartFile 객체로 생성한다.
MultipartFile file = multipartRequest.getFile("attachfile");

// 최대업로드사이즈 초과 체크
if( file == null ) {
    Exception e = (Exception)multipartRequest.getAttribute("exception");
    if( e instanceof MaxUploadSizeExceededException ) {
       long maxFileSizeMB = (((MaxUploadSizeExceededException)e).getMaxUploadSize() / 1024 / 1024);
       errorMsg = "첨부파일 사이즈는 " + maxFileSizeMB + "M 를 초과할 수 없습니다.";
    }
    Log.error(e, "파일생성 중 예외발생");
    return "/error";
}

4. 활용방안
로그인한 회원의 권한에 따라서 크기를 다르게 설정해야 하는 요건의 경우에도 활용가능하다이를 테면 관리자 권한이나 수퍼유저의 경우 일반유저보다 큰 파일을 업로드 할 수 있다.

5. 개선할 점
요청 URL에 따라서 다른 상수클래스를 사용하는 부분에서 요청 URL이 하드코딩 되어있다그런데 명명규칙이 표준화되어 있어서 요청 URL과 상수클래스간에 일정한 규칙이 존재한다면 하드코딩된 부분을 제거할 수 있고이후 추가되는 업무에 따른 URL에 대해서도 소스코드 수정없이 적용이 가능할 것이다.

6. 참고

댓글 없음:

댓글 쓰기