使用REST模板Java Spring MVC从服务器下载大文件

我有一个REST服务,可以向我发送一个较大的ISO文件,REST服务中没有任何问题。现在,我编写了一个Web应用程序,该应用程序调用其余服务以获取文件,在客户端(Web应用程序)端,我收到内存不足异常。下面是我的代码

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 MB。谁能帮忙。

异常堆栈:

  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();

}

回答:

这是我的方法。基于springJira问题的提示。

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);

从前面提到的吉拉问题:

请注意,你不能简单地从提取器返回InputStream,因为到execute方法返回时,基础连接和流已经关闭。

Update for Spring 5

Spring 5引入了WebClient允许异步(例如,非阻塞)http请求的类。从文档:

与RestTemplate相比,WebClient是:

  • non-blocking, reactive, and supports higher concurrency with less hardware resources.
  • provides a functional API that takes advantage of Java 8 lambdas.
  • supports both synchronous and asynchronous scenarios.
  • supports streaming up or down from a server.

以上是 使用REST模板Java Spring MVC从服务器下载大文件 的全部内容, 来源链接: utcz.com/qa/416731.html

回到顶部