如何异步将HttpHeader写入ClientHttpResponse?

时间:2018-12-11 11:17:28

标签: java spring spring-mvc resttemplate spring-rest

我正在创建一个应该提供下载文件的网络服务。文件本身是从内部的另一个外部Web服务请求的。所以我的网络服务更像是代理。

由于文件可能很大,而不是完全提取它们,因此我将文件直接作为流写入。

问题:外部Web服务提供了HttpHeaders,例如Content-LengthContent-TypeContent-Disposition,我想通过代理Servlet进行转发。但是,由于我仅流式传输资源,因此在此阶段尚不了解标头。

@GetMapping(value = "/files/{filename}")
public ResponseEntity<StreamingResponseBody> getDocument(@PathVariable String filename) {
    StreamingResponseBody responseBody = outputStream -> {
        HttpHeaders headers = download(outputStream, filename);
        outputStream.close();
        System.out.println(headers); //always 'null' at this stage
    };

    return ResponseEntity.ok(responseBody); //TODO how to get the header in?
}

private HttpHeaders download(OutputStream outputStream, String filename) {
        ResponseExtractor<HttpHeaders> responseExtractor = clientHttpResponse -> {
            //directly stream the remote file into the servlet response
            InputStream inputStream = clientHttpResponse.getBody();
            StreamUtils.copy(inputStream, outputStream);

            HttpHeaders headers = clientHttpResponse.getHeaders();
            System.out.println(headers); //external headers are shown correctly

            //is it possible to write the headers into the servlet response at this stage??
            return headers;
        };

        return restTemplate.execute("https://www.external-webservice.com?file=" + filename, HttpMethod.GET, null, responseExtractor);
    }

如您所见:外部文件的标头在ResponseExtractor阶段可用。但是,当我将这些标头返回到StreamingResponseBody阶段时,标头为null

问题:在直接流式传输的情况下,是否有可能获得远程HttpHeaders?

1 个答案:

答案 0 :(得分:0)

在编写正文流之前,必须将HttpHeaders直接写入HttpServletResponse

private HttpHeaders download(OutputStream outputStream, HttpServletResponse response, String filename) {
    ResponseExtractor<Void> responseExtractor = clientHttpResponse -> {
        response.setHeader(HttpHeaders.CONTENT_DISPOSITION, clientHttpResponse.getHeaders().getFirst(HttpHeaders.CONTENT_DISPOSITION));

        InputStream inputStream = clientHttpResponse.getBody();
        StreamUtils.copy(inputStream, outputStream);
        return null;
    };
}