Как получить InputStream через Spring-Feign? - PullRequest
1 голос
/ 22 сентября 2019

Я хочу скачать и сохранить файл в локальном каталоге с сервера Spring-OpenFeign с нулевой копией.

Наивный метод загрузки следующим образом:

import org.apache.commons.io.FileUtils

@GetMapping("/api/v1/files")
ResponseEntity<byte[]> getFile(@RequestParam(value = "key") String key)

ResponseEntity<byte[]> resp = getFile("filename.txt")
File fs = new File("/opt/test")
FileUtils.write(file, resp.getBody())

В этом кодепоток данных будет выглядеть следующим образом: feign Internal Stream -> Buffer -> ByteArray -> Buffer -> File

Как можно эффективно и быстрее сохранить файл памяти и сохранить его?

1 Ответ

0 голосов
/ 22 сентября 2019

TL; DR.Используйте ResponseEntity<InputStreamResource> и Java NIO

Согласно SpringDecoder , ответ декодирования Spring с использованием HttpMessageConverters

ResourceHttpMessageConverter, который является одним из возвращаемых HttpMesageConverters InputStreamResource , которые содержатInputStream и имя файла получены из Content-Disposition.

Но, ResourceHttpMessageConverter должен быть инициализирован supportsReadStreaming = true (default value) Если у вас есть дальнейшие интересы в этой реализации, проверьте этот код .

Итак, измененный код выглядит следующим образом:

@GetMapping("/api/v1/files")
ResponseEntity<InputStreamResource> getFile(@RequestParam(value = "key") String key)

JDK9

try (OutputStream os = new FileOutputStream("filename.txt")) {
    responeEntity.getBody().getInputStream().transferTo(os);
}

JDK8 или меньше

Использовать Guava ByteStreams.copy ()

Path p = Paths.get(responseEntity.getFilename())
ReadableByteChannel rbc = Channels.newChannel(responeEntity.getBody().getInputStream())
try(FileChannel fc = FileChannel.open(p, StandardOpenOption.WRITE)) {
    ByteStreams.copy(rbc, fc)
}

Сейчас,Feign Internal Stream -> File

...