У меня есть 3 отдельных веб-приложения spring
- A использует spring 4.x
- B использует spring 3.2.0
- C использует spring 4.x
B и C предоставляет контроллеры REST для загрузки файлов
- A читает файл и загружает его в B
- B отправляет запрос C без необходимости читать содержимое файла
- а затем C делает все, что захочет, с файлом.
Таким образом, поток будет A- > B- > C
Мой вопрос: возможно ли установить B таким образом, чтобы B не сохранял весь файл в памяти, но читал бы входящий поток и переместите его на C?
Что мне удалось сделать: А
public void sendFileFromA() throws FileNotFoundException {
final InputStream fis = new FileInputStream(new File("someFile"));
final RequestCallback requestCallback = new RequestCallback() {
@Override
public void doWithRequest(final ClientHttpRequest request) throws IOException {
request.getHeaders().add("Content-type", "application/octet-stream");
IOUtils.copy(fis, request.getBody());
}
};
final RestTemplate restTemplate = new RestTemplate();
SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
requestFactory.setBufferRequestBody(false);
restTemplate.setRequestFactory(requestFactory);
final HttpMessageConverterExtractor<String> responseExtractor = new HttpMessageConverterExtractor<>(
String.class, restTemplate.getMessageConverters());
restTemplate.execute("http://b_url/upload", HttpMethod.POST, requestCallback, responseExtractor);
}
В
@RequestMapping(value = "/upload", method = RequestMethod.POST)
public @ResponseBody String handleFileUpload(HttpServletRequest request) throws IOException {
final ServletInputStream input = request.getInputStream();
final RequestCallback requestCallback = new RequestCallback() {
@Override
public void doWithRequest(final ClientHttpRequest request) throws IOException {
request.getHeaders().add("Content-type", "application/octet-stream");
try (OutputStream body = request.getBody()) {
IOUtils.copy(input, body);
}
}
};
final RestTemplate restTemplate = new RestTemplate();
SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
requestFactory.setBufferRequestBody(false);
restTemplate.setRequestFactory(requestFactory);
final HttpMessageConverterExtractor<String> responseExtractor = new HttpMessageConverterExtractor<>(
String.class, restTemplate.getMessageConverters());
restTemplate.execute("http://c_url/upload", HttpMethod.POST, requestCallback, responseExtractor);
return "success";
}
С
@RequestMapping(value = "/upload", method = RequestMethod.POST)
public @ResponseBody String handleFileUpload(HttpServletRequest request) throws IOException {
ServletInputStream input = request.getInputStream();
try (BufferedOutputStream output = new BufferedOutputStream(new FileOutputStream("zibiTest"))) {
IOUtils.copy(input, output);
}
return "success";
}
Я могу легко копировать файлы более > 10 ГБ с A на C с помощью B.
С таким решением мы можем попытаться остановить A во время передачи, B и C должны быть уведомлены об ошибке, но иногда бывает так, что сообщение об ошибке не достигает C - он закрывается с исключением тайм-аута сокета, любая идея почему это происходит и как правильно его реализовать?
Является ли этот подход действительным или его можно обработать лучше?