[SPRING] REST 템플릿을 사용하여 서버에서 대용량 파일 다운로드 Java Spring MVC
SPRINGREST 템플릿을 사용하여 서버에서 대용량 파일 다운로드 Java Spring MVC
나에게 큰 ISO 파일을 보내는 REST 서비스가있다. REST 서비스에는 문제가 없다. 이제 클라이언트 (웹 응용 프로그램) 쪽에서 파일을 가져 오기 위해 나머지 서비스를 호출하는 웹 응용 프로그램을 작성했습니다. Out Of Memory Exception.Below는 제 코드입니다.
HttpHeaders headers = new HttpHeaders();//1 Line
headers.setAccept(Arrays.asList(MediaType.APPLICATION_OCTET_STREAM));//2 Line
headers.set("Content-Type","application/json");//3 Line
headers.set("Cookie", "session=abc");//4 Line
HttpEntity statusEntity=new HttpEntity(headers);//5 Line
String uri_status=new String("http://"+ip+":8080/pcap/file?fileName={name}");//6 Line
ResponseEntity<byte[]>resp_status=rt.exchange(uri_status, HttpMethod.GET, statusEntity, byte[].class,"File5.iso");//7 Line
내가 7 라인에서 메모리 예외를 수신, 내가 버퍼와 부품을 얻을 것이라고 추측하지만, 내가 어떻게 서버 에서이 파일을 얻을 수있는 몰라, 파일의 크기는 약 500에서 700 메가 바이트입니다. 누구든지 도와주세요.
예외 스택 :
org.springframework.web.util.NestedServletException: Handler processing failed; nested exception is java.lang.OutOfMemoryError: Java heap space
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:972)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:852)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:882)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:778)
javax.servlet.http.HttpServlet.service(HttpServlet.java:622)
javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
root cause
java.lang.OutOfMemoryError: Java heap space
java.util.Arrays.copyOf(Arrays.java:3236)
java.io.ByteArrayOutputStream.grow(ByteArrayOutputStream.java:118)
java.io.ByteArrayOutputStream.ensureCapacity(ByteArrayOutputStream.java:93)
java.io.ByteArrayOutputStream.write(ByteArrayOutputStream.java:153)
org.springframework.util.FileCopyUtils.copy(FileCopyUtils.java:113)
org.springframework.util.FileCopyUtils.copyToByteArray(FileCopyUtils.java:164)
org.springframework.http.converter.ByteArrayHttpMessageConverter.readInternal(ByteArrayHttpMessageConverter.java:58)
org.springframework.http.converter.ByteArrayHttpMessageConverter.readInternal(ByteArrayHttpMessageConverter.java:1)
org.springframework.http.converter.AbstractHttpMessageConverter.read(AbstractHttpMessageConverter.java:153)
org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:81)
org.springframework.web.client.RestTemplate$ResponseEntityResponseExtractor.extractData(RestTemplate.java:627)
org.springframework.web.client.RestTemplate$ResponseEntityResponseExtractor.extractData(RestTemplate.java:1)
org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:454)
org.springframework.web.client.RestTemplate.execute(RestTemplate.java:409)
org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:385)
com.pcap.webapp.HomeController.getPcapFile(HomeController.java:186)
내 서버 측 REST 서비스 코드는 잘 작동합니다.
@RequestMapping(value = URIConstansts.GET_FILE, produces = { MediaType.APPLICATION_OCTET_STREAM_VALUE}, method = RequestMethod.GET)
public void getFile(@RequestParam(value="fileName", required=false) String fileName,HttpServletRequest request,HttpServletResponse response) throws IOException{
byte[] reportBytes = null;
File result=new File("/home/arpit/Documents/PCAP/dummyPath/"+fileName);
if(result.exists()){
InputStream inputStream = new FileInputStream("/home/arpit/Documents/PCAP/dummyPath/"+fileName);
String type=result.toURL().openConnection().guessContentTypeFromName(fileName);
response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
response.setHeader("Content-Type",type);
reportBytes=new byte[100];//New change
OutputStream os=response.getOutputStream();//New change
int read=0;
while((read=inputStream.read(reportBytes))!=-1){
os.write(reportBytes,0,read);
}
os.flush();
os.close();
}
해결법
-
==============================
1.여기 내가 어떻게하는지. 이 Spring Jira 문제의 힌트를 기반으로합니다.
여기 내가 어떻게하는지. 이 Spring Jira 문제의 힌트를 기반으로합니다.
RestTemplate restTemplate // = ...; // Optional Accept header RequestCallback requestCallback = request -> request.getHeaders() .setAccept(Arrays.asList(MediaType.APPLICATION_OCTET_STREAM, MediaType.ALL)); // Streams the response instead of loading it all in memory ResponseExtractor<Void> responseExtractor = response -> { // Here I write the response to a file but do what you like Path path = Paths.get("some/path"); Files.copy(response.getBody(), path); return null; }; restTemplate.execute(URI.create("www.something.com"), HttpMethod.GET, requestCallback, responseExtractor);
앞서 언급 한 Jira 문제에서 :
Spring 5는 비동기 (예 : 비 차단) http 요청을 허용하는 WebClient 클래스를 도입했습니다. 문서에서 :
-
==============================
2.이렇게하면 전체 요청을 메모리에로드하지 못하게됩니다.
이렇게하면 전체 요청을 메모리에로드하지 못하게됩니다.
SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory(); requestFactory.setBufferRequestBody(false); RestTemplate rest = new RestTemplate(requestFactory);
java.lang.OutOfMemoryError : Java 힙 공간을 해결하면 JVM에 더 많은 메모리를 추가 할 수 있습니다.
아마도 당신이 가진 문제는 당신이 실행하려고하는 요청 (엄청나게 큰 파일을 다운로드)과 엄격하게 관련되어 있지는 않지만, 그 프로세스를 위해 할당 된 메모리는 충분하지 않다.
-
==============================
3.파일 스트림이 메모리에로드되지 않도록 다중 파트 첨부 파일을 사용해야합니다. 이 예제에서는 Apache CXF로 구현 된 휴식 서비스를 사용합니다.
파일 스트림이 메모리에로드되지 않도록 다중 파트 첨부 파일을 사용해야합니다. 이 예제에서는 Apache CXF로 구현 된 휴식 서비스를 사용합니다.
... import org.apache.cxf.jaxrs.ext.multipart.Attachment; ... @Override @Path("/put") @Consumes("multipart/form-data") @Produces({ "application/json" }) @POST public SyncResponseDTO put( List<Attachment> attachments) { SyncResponseDTO response = new SyncResponseDTO(); try { for (Attachment attr : attachments) { log.debug("get input filestream: " + new Date()); InputStream is = attr.getDataHandler().getInputStream();
from https://stackoverflow.com/questions/32988370/download-large-file-from-server-using-rest-template-java-spring-mvc by cc-by-sa and MIT license
'SPRING' 카테고리의 다른 글
[SPRING] 페이스 북 토큰을 인증에 사용하는 Stateless REST Endpoint 용 스프링 소셜 인증 필터 (0) | 2018.12.20 |
---|---|
[SPRING] 스프링 mvc에서 컨트롤러에서 아약스로 객체를 반환하는 법 (0) | 2018.12.20 |
[SPRING] 봄 - 최대 절전 모드 5 명명 전략 구성 (0) | 2018.12.19 |
[SPRING] Spring Boot에서 HTTP OPTIONS 요청을 처리하는 방법은 무엇입니까? (0) | 2018.12.19 |
[SPRING] 페이징이있는 Spring-Data FETCH JOIN이 작동하지 않습니다. (0) | 2018.12.19 |