Spring WebClient: Как передать большой байт [] в файл? - PullRequest
7 голосов
/ 19 мая 2019

Похоже, что Spring RestTemplate не может передавать ответ непосредственно в файл, не буферизуя его в памяти. Как правильно добиться этого, используя более новую Spring 5 WebClient?

WebClient client = WebClient.create("https://example.com");
client.get().uri(".../{name}", name).accept(MediaType.APPLICATION_OCTET_STREAM)
                    ....?

Я вижу, что люди нашли несколько обходных путей / хаков к этой проблеме с RestTemplate, но я больше заинтересован в том, чтобы сделать это правильно с WebClient.

Существует множество примеров использования RestTemplate для загрузки двоичных данных, но почти все они загружают byte[] в память.

Ответы [ 2 ]

1 голос
/ 23 мая 2019

Я не могу проверить, эффективно ли следующий код не буферизует содержимое полезной нагрузки webClient в памяти. Тем не менее, я думаю, что вы должны начать оттуда:

public Mono<Void> testWebClientStreaming() throws IOException {
    Flux<DataBuffer> stream = 
            webClient
                    .get().accept(MediaType.APPLICATION_OCTET_STREAM)
                    .retrieve()
            .bodyToFlux(DataBuffer.class);
    Path filePath = Paths.get("filename");
    AsynchronousFileChannel asynchronousFileChannel = AsynchronousFileChannel.open(filePath, WRITE);
    return DataBufferUtils.write(stream, asynchronousFileChannel)
            .doOnNext(DataBufferUtils.releaseConsumer())
            .doAfterTerminate(() -> {
                try {
                    asynchronousFileChannel.close();
                } catch (IOException ignored) { }
            }).then();
}
0 голосов
/ 26 мая 2019

Я не уверен, есть ли у вас доступ к RestTemplate при вашем текущем использовании пружины, но этот сработал для меня.


RestTemplate restTemplate // = ...;

RequestCallback requestCallback = request -> request.getHeaders()
        .setAccept(Arrays.asList(MediaType.APPLICATION_OCTET_STREAM, MediaType.ALL));

// Streams the response
ResponseExtractor<Void> responseExtractor = response -> {
    // Here I write the response to a file but do what you like
    Path path = Paths.get("http://some/path");
    Files.copy(response.getBody(), path);
    return null;
};
restTemplate.execute(URI.create("www.something.com"), HttpMethod.GET, requestCallback, responseExtractor);

...