在系统 A->B->C 之间发送文件,而不将整个文件存储在 B 中
2022-09-04 04:22:10
我有3个单独的弹簧Web应用程序
- A使用弹簧4.x
- B 使用弹簧 3.2.0
- C 使用弹簧 4.x
B 和 C 公开了用于上传文件的 REST 控制器
- A 读取文件并将其上载到 B
- B 将请求发送到 C,无需读取文件内容
- 然后C对文件做任何它想要的操作。
因此,流量将为 A->B->C
我的问题是 - 是否可以以这种方式设置B,以便B不会将整个文件存储在内存中,而是读取传入的流并将其转发到C?
我设法做的是:A
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);
}
B
@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";
}
C
@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";
}
我可以使用B轻松地将超过>10GB的文件从A复制到C。
使用这样的解决方案,我们可以尝试在传输时停止A,B和C应该收到有关错误的通知,但有时会发生错误消息未到达C的情况 - 它会以套接字超时异常关闭,任何想法为什么会发生这种情况以及如何正确实现它?
这是一种有效的方法,还是可以更好地处理?