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. 참고
댓글 없음:
댓글 쓰기