fileupload 용량제한 관련 수정

dev
박성영 5 months ago
parent f3f7a96f8f
commit 1def698009

@ -1,15 +1,18 @@
package egovframework.exception;
import egovframework.util.ApiResponseEntity;
import egovframework.util.FileUtil;
import egovframework.util.HttpServletUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.web.servlet.MultipartProperties;
import org.springframework.dao.DataAccessException;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.transaction.TransactionException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.multipart.MaxUploadSizeExceededException;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
@ -27,6 +30,11 @@ import java.io.IOException;
@RequiredArgsConstructor
public class EgovExceptionAdvice {
/**
*
*/
private final MultipartProperties multipartProperties;
/**
* DataAccessException
* .
@ -107,6 +115,35 @@ public class EgovExceptionAdvice {
log.warn("MessageException 발생: {}", e.getMessage());
return getModelAndView(e, request, HttpStatus.INTERNAL_SERVER_ERROR);
}
/**
* MaxUploadSizeExceededException
* .
*
* @param e
* @param request HTTP
* @return AJAX ResponseEntity, ModelAndView
*/
@ExceptionHandler(MaxUploadSizeExceededException.class)
public Object handleMaxUploadSizeExceededException(MaxUploadSizeExceededException e, HttpServletRequest request) {
// 파일 크기 제한 초과 예외는 한 번만 로깅
log.warn("파일 업로드 크기 제한 초과: {}", e.getMessage());
// 설정된 파일 크기 제한 정보 가져오기
long maxFileSize = multipartProperties.getMaxFileSize().toBytes();
long maxRequestSize = multipartProperties.getMaxRequestSize().toBytes();
// 커스텀 예외로 변환
String message = String.format("파일 크기가 제한을 초과했습니다. 최대 %s까지 가능합니다.",
FileUtil.formatFileSize(maxFileSize));
FileUploadLimitExceededException customException =
new FileUploadLimitExceededException(message, maxFileSize, maxRequestSize, e);
// 통일된 방식으로 예외 처리
return getModelAndView(customException, request, HttpStatus.BAD_REQUEST);
}
/**
*

@ -0,0 +1,119 @@
package egovframework.exception;
import egovframework.util.FileUtil;
import lombok.Getter;
import org.springframework.web.multipart.MaxUploadSizeExceededException;
/**
*
*
* .
* .
*
* Spring Boot MaxUploadSizeExceededException
* .
*/
@Getter
public class FileUploadLimitExceededException extends RuntimeException {
private static final long serialVersionUID = 1L;
/**
*
*/
private final String errorCode;
/**
* ( )
*/
private final long maxFileSize;
/**
* ( )
*/
private final long maxRequestSize;
/**
* ( , )
*/
private final long actualFileSize;
/**
*
*
* @param message
* @param maxFileSize ( )
* @param maxRequestSize ( )
* @param cause
*/
public FileUploadLimitExceededException(String message, long maxFileSize, long maxRequestSize, MaxUploadSizeExceededException cause) {
super(message, cause);
this.errorCode = "FILE_SIZE_EXCEEDED";
this.maxFileSize = maxFileSize;
this.maxRequestSize = maxRequestSize;
this.actualFileSize = extractActualFileSize(cause);
}
/**
* .
*
* @param cause
* @return ( ), -1
*/
private long extractActualFileSize(MaxUploadSizeExceededException cause) {
if (cause == null) {
return -1;
}
// MaxUploadSizeExceededException의 메시지에서 실제 파일 크기를 추출
// 예: "the request was rejected because its size (3520463011) exceeds the configured maximum (10485760)"
String message = cause.getMessage();
if (message == null) {
return -1;
}
try {
// 괄호 안의 첫 번째 숫자를 추출
int startIndex = message.indexOf('(');
int endIndex = message.indexOf(')', startIndex);
if (startIndex >= 0 && endIndex > startIndex) {
String sizeStr = message.substring(startIndex + 1, endIndex).trim();
return Long.parseLong(sizeStr);
}
} catch (Exception e) {
// 추출 실패 시 무시
}
return -1;
}
/**
* .
*
* @return (: "10MB")
*/
public String getHumanReadableMaxFileSize() {
return FileUtil.formatFileSize(maxFileSize);
}
/**
* .
*
* @return (: "50MB")
*/
public String getHumanReadableMaxRequestSize() {
return FileUtil.formatFileSize(maxRequestSize);
}
/**
* .
*
* @return (: "15MB"), "알 수 없음"
*/
public String getHumanReadableActualFileSize() {
if (actualFileSize < 0) {
return "알 수 없음";
}
return FileUtil.formatFileSize(actualFileSize);
}
}

@ -637,4 +637,22 @@ public class FileUtil {
return filename.substring(lastDotIndex + 1).toLowerCase();
}
/**
* .
*
* @param bytes
* @return (: "10MB", "1.5GB")
*/
public static String formatFileSize(long bytes) {
if (bytes < 1024) {
return bytes + "B";
} else if (bytes < 1024 * 1024) {
return String.format("%.2fKB", bytes / 1024.0);
} else if (bytes < 1024 * 1024 * 1024) {
return String.format("%.2fMB", bytes / (1024.0 * 1024.0));
} else {
return String.format("%.2fGB", bytes / (1024.0 * 1024.0 * 1024.0));
}
}
}

@ -7,15 +7,17 @@ server:
charset: UTF-8
enabled: true
force: true # 서버가 지정한 인코딩(UTF-8)을 항상 강제로 적용, 클라이언트의 요청과 상관없이 서버 인코딩이 우선
multipart:
max-file-size: 10MB
max-request-size: 50MB
Globals:
DbType: maria
# Common application properties
spring:
servlet:
multipart: # 서블릿단에서 용량제한을 걸면, 브라우저 자체에서 서버와 접속이 안되는걸로 판단, 여러 스레드로 시도하게 됨, 막기위해서는 클라이언트에서도 용량제한 체크 필수
max-file-size: 10MB
max-request-size: 50MB
resolve-lazily: false # 즉시 처리하여 빠른 에러 응답
profiles:
active: local
application:
@ -132,6 +134,7 @@ interceptor:
- /favicon.ico #파비콘
- /swagger-ui/** #Swagger UI
- /v3/api-docs/** #Swagger API 문서
- /test/**
refererExclude:
- /** #모두 승인 (개발 시에만)
- /login/** #로그인 관련 페이지
@ -141,3 +144,4 @@ interceptor:
- /common/** #공통 페이지
- /swagger-ui/** #Swagger UI
- /v3/api-docs/** #Swagger API 문서
- /test/**

Loading…
Cancel
Save