대용량 다운로드 테스트
This commit is contained in:
@@ -1,98 +1,64 @@
|
||||
package com.kamco.cd.kamcoback.config;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.kamco.cd.kamcoback.common.utils.HeaderUtil;
|
||||
import com.kamco.cd.kamcoback.common.download.dto.DownloadAuditEvent;
|
||||
import com.kamco.cd.kamcoback.common.utils.UserUtil;
|
||||
import com.kamco.cd.kamcoback.config.api.ApiLogFunction;
|
||||
import com.kamco.cd.kamcoback.menu.dto.MenuDto;
|
||||
import com.kamco.cd.kamcoback.menu.service.MenuService;
|
||||
import com.kamco.cd.kamcoback.postgres.entity.AuditLogEntity;
|
||||
import com.kamco.cd.kamcoback.postgres.repository.log.AuditLogRepository;
|
||||
import jakarta.servlet.DispatcherType;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.util.Comparator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class FileDownloadInteceptor implements HandlerInterceptor {
|
||||
|
||||
private final AuditLogRepository auditLogRepository;
|
||||
private final MenuService menuService;
|
||||
private final ApplicationEventPublisher publisher;
|
||||
private final UserUtil userUtil;
|
||||
|
||||
@Autowired private ObjectMapper objectMapper;
|
||||
|
||||
public FileDownloadInteceptor(
|
||||
AuditLogRepository auditLogRepository, MenuService menuService, UserUtil userUtil) {
|
||||
this.auditLogRepository = auditLogRepository;
|
||||
this.menuService = menuService;
|
||||
this.userUtil = userUtil;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean preHandle(
|
||||
HttpServletRequest request, HttpServletResponse response, Object handler) {
|
||||
public void afterCompletion(
|
||||
HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
|
||||
|
||||
if (!request.getRequestURI().contains("/download")) return true;
|
||||
String uri = request.getRequestURI();
|
||||
if (uri == null || !uri.contains("/download")) return;
|
||||
if (request.getDispatcherType() != DispatcherType.REQUEST) return;
|
||||
|
||||
if (request.getDispatcherType() != jakarta.servlet.DispatcherType.REQUEST) {
|
||||
return true;
|
||||
}
|
||||
|
||||
saveLog(request, response);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void saveLog(HttpServletRequest request, HttpServletResponse response) {
|
||||
// 파일 다운로드 API만 필터링
|
||||
if (!request.getRequestURI().contains("/download")) {
|
||||
Long userId;
|
||||
try {
|
||||
userId = userUtil.getId();
|
||||
if (userId == null) return; // userId null 불가면 스킵
|
||||
} catch (Exception e) {
|
||||
log.warn("Download audit userId resolve failed. uri={}, err={}", uri, e.toString());
|
||||
return;
|
||||
}
|
||||
|
||||
Long userId = userUtil.getId();
|
||||
String ip = ApiLogFunction.getClientIp(request);
|
||||
int status = response.getStatus();
|
||||
String normalizedUri = uri.replace("/api", "");
|
||||
|
||||
List<?> list = menuService.getFindAll();
|
||||
List<MenuDto.Basic> result =
|
||||
list.stream()
|
||||
.map(
|
||||
item -> {
|
||||
if (item instanceof LinkedHashMap<?, ?> map) {
|
||||
return objectMapper.convertValue(map, MenuDto.Basic.class);
|
||||
} else if (item instanceof MenuDto.Basic dto) {
|
||||
return dto;
|
||||
} else {
|
||||
throw new IllegalStateException("Unsupported cache type: " + item.getClass());
|
||||
}
|
||||
})
|
||||
.toList();
|
||||
UUID downloadUuid = extractUuidFromUri(uri);
|
||||
if (downloadUuid == null) {
|
||||
log.warn("Download UUID parse failed. uri={}", uri);
|
||||
return; // downloadUuid null 불가 -> 스킵
|
||||
}
|
||||
|
||||
String normalizedUri = request.getRequestURI().replace("/api", "");
|
||||
MenuDto.Basic basic =
|
||||
result.stream()
|
||||
.filter(
|
||||
menu -> menu.getMenuUrl() != null && normalizedUri.startsWith(menu.getMenuUrl()))
|
||||
.max(Comparator.comparingInt(m -> m.getMenuUrl().length()))
|
||||
.orElse(null);
|
||||
publisher.publishEvent(
|
||||
new DownloadAuditEvent(userId, uri, normalizedUri, ip, status, downloadUuid));
|
||||
}
|
||||
|
||||
AuditLogEntity log =
|
||||
AuditLogEntity.forFileDownload(
|
||||
userId,
|
||||
request.getRequestURI(),
|
||||
Objects.requireNonNull(basic).getMenuUid(),
|
||||
ip,
|
||||
response.getStatus(),
|
||||
UUID.fromString(HeaderUtil.get(request, "kamco-download-uuid")));
|
||||
|
||||
auditLogRepository.save(log);
|
||||
private UUID extractUuidFromUri(String uri) {
|
||||
try {
|
||||
String[] parts = uri.split("/");
|
||||
String last = parts[parts.length - 1];
|
||||
return UUID.fromString(last);
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user