사용자가 파일을 다운로드 할 수있는 Spring-MVC 애플리케이션을 개발 중입니다. 사용자는 다운로드 메커니즘을 트리거하는 첨부 파일을 클릭 할 수 있습니다.
어제 여러 다운로드 중 2 개에 약 2GB의 파일이있을 때 메모리 부족 오류 (아래 로그)가 발생했습니다.
이 문제를 피하기 위해이 문제를 해결하는 한 가지 방법은 다운로드 데이터를 청크로 스트리밍하고 전체 파일이 아닌 서비스 계층에서 해당 청크 만 처리하는 것처럼 보였습니다.
불행히도 나는 이것으로 진행하는 방법을 모릅니다. 어떤 도움이라도 좋을 것입니다. 이 옵션이 비행 할 수없는 경우이 문제를 해결하는 방법에 대한 권장 사항입니다.
오류 기록 :
HTTP Status 500 - Handler processing failed; nested exception is java.lang.OutOfMemoryError: Direct buffer memory
type Exception report
message Handler processing failed; nested exception is java.lang.OutOfMemoryError: Direct buffer memory
description The server encountered an internal error that prevented it from fulfilling this request.
exception
org.springframework.web.util.NestedServletException: Handler processing failed; nested exception is java.lang.OutOfMemoryError: Direct buffer memory
org.springframework.web.servlet.DispatcherServlet.triggerAfterCompletionWithError(DispatcherServlet.java:1303)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:977)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:967)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:858)
javax.servlet.http.HttpServlet.service(HttpServlet.java:620)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:843)
컨트롤러 코드 :
@RequestMapping(value = "/download/attachment/{attachid}", method = RequestMethod.GET)
public void getAttachmentFromDatabase(@PathVariable("attachid") int attachid,
, HttpServletResponse response,) {
response.setContentType("application/octet-stream");
GroupAttachments groupAttachments = this.groupAttachmentsService.getAttachmenById(attachid);
response.setHeader("Content-Disposition", "attachment; filename=\"" + groupAttachments.getFileName() + "\"");
response.setContentLength(groupAttachments.getSendAttachment().length);
FileCopyUtils.copy(groupAttachments.getSendAttachment(), response.getOutputStream());
response.flushBuffer();
}
서비스 계층 :
@Override
public GroupAttachments getAttachmenById(int attachId) {
Person person = this.personService.getCurrentlyAuthenticatedUser();
GroupAttachments groupAttachments = this.groupAttachmentsDAO.getAttachmenById(attachId);
GroupMembers groupMembers = this.groupMembersService.returnMembersMatchingUsernameAccountId(person.getUsername(),
groupAttachments.getGroupId());
if (!(groupMembers == null)) {
if (person.getUsername().equals(groupMembers.getMemberUsername())) {
try {
Path path = Paths.get(msg + groupAttachments.getGroupId() + "/" +
groupAttachments.getFileIdentifier());
groupAttachments.setSendAttachment(Files.readAllBytes(path));
return groupAttachments;
} catch (IOException ignored) {
this.groupAttachmentsDAO.removeAttachment(attachId);
return null;
}
}
return null;
} else {
return null;
}
}
감사합니다. :-)
최신 정보
새로운 다운로드 메커니즘 :
컨트롤러 :
public ResponseEntity<byte[]> getAttachmentFromDatabase(@PathVariable("attachid") int attachid,
@PathVariable("groupaccountid") Long groupAccountId, @PathVariable("api") String api,
HttpServletResponse response,
@PathVariable("type") boolean type) {
Path path = this.groupAttachmentsService.getAttachmentPathById(attachid);
GroupAttachments groupAttachments = this.groupAttachmentsService.getAttachmentObjectOnlyById(attachid);
response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition", "attachment; filename=\""+groupAttachments.getFileName()+"\"");
try {
OutputStream outputStream = response.getOutputStream();
Files.copy(path,outputStream);
outputStream.flush();
outputStream.close();
response.flushBuffer();
}
서비스 계층 :
@Override
public Path getAttachmentPathById(int attachId){
Person person = this.personService.getCurrentlyAuthenticatedUser();
GroupAttachments groupAttachments = this.groupAttachmentsDAO.getAttachmenById(attachId);
GroupMembers groupMembers = this.groupMembersService.returnMembersMatchingUsernameAccountId(person.getUsername(),
groupAttachments.getGroupId());
if (!(groupMembers == null)) {
if (person.getUsername().equals(groupMembers.getMemberUsername())) {
try {
return Paths.get(msg + groupAttachments.getGroupId() + "/" +
groupAttachments.getFileIdentifier());
} catch (Exception ignored) {
return null;
}
}
return null;
} else {
return null;
}
}
먼저 전체 파일 콘텐츠를 메모리에로드하므로 서비스의 전체 콘텐츠로드를 중지합니다.
를 구성하는 방법 작성 Path
를 들어 GroupAttachments
, 나는에 그것을 만들 것 GroupAttachments
그 자체.
public class GroupAttachments {
public Path getPath() {
return Paths.get(msg + getGroupId() + "/" + getFileIdentifier());
}
}
그런 다음 컨트롤러에서 간단히
@RequestMapping(value = "/download/attachment/{attachid}", method = RequestMethod.GET)
public void getAttachmentFromDatabase(@PathVariable("attachid") int attachid, HttpServletResponse response) {
response.setContentType("application/octet-stream");
GroupAttachments groupAttachments = this.groupAttachmentsService.getAttachmenById(attachid);
Path path = groupAttachmetns.getPath(); // calculates the java.nio.file.Path
response.setHeader("Content-Disposition", "attachment; filename=\"" + path.getFileName() + "\"");
response.setContentLength(Files.size(path);
Files.copy(path, response.getOutputStream());
response.flushBuffer();
}
더 복잡하게 만들 필요가 없습니다.
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다