加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

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

发布时间:2020-12-15 07:38:17 所属栏目:Java 来源:网络整理
导读:我有一个REST服务,它向我发送一个大的ISO文件,REST服务中没有问题. 现在我已经编写了一个Web应用程序,它调用其余服务来获取文件,在客户端(Web应用程序)端我收到Out Of memory Exception.Below是我的代码 HttpHeaders headers = new HttpHeaders();//1 Line h
我有一个REST服务,它向我发送一个大的ISO文件,REST服务中没有问题.
现在我已经编写了一个Web应用程序,它调用其余服务来获取文件,在客户端(Web应用程序)端我收到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 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,read);
        }
        os.flush();
        os.close();






    }

解决方法

我就是这样做的.基于此 Spring Jira issue的提示.

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"),requestCallback,responseExtractor);

从前面提到的Jira问题:

Note that you cannot simply return the InputStream from the extractor,because by the time the execute method returns,the underlying connection and stream are already closed.

春季5的更新

Spring 5引入了WebClient类,它允许异步(例如非阻塞)http请求.来自doc:

By comparison to the RestTemplate,the WebClient is:

  • 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.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读