我有一个用java和springboot编写的文件传输服务,它将文件从源文件流到目标文件,而不需要任何本地存储。
它从源获取inputstream的句柄,从目标获取outputstream的句柄,并有效地执行以下操作以流式传输文件。
IOUtils.copy(inputStream, outputStream);
Destination InputStream -> IOUtils.copy -> Destination OutputStream
现在我有另一个需求,我需要调用一个加密api,它接受application/oct-ect流并返回相同的流。api在客户端提供数据时对数据进行加密,同时以流的形式返回数据。我使用以下命令使用curl测试了api:
curl -v -X POST -H "Content-Type:application/octet-stream" -H "Accept:application/octet-stream" --data-binary @test-file -o test-file.enc http://127.0.0.1:1234/encrypt/test-file
现在,我需要将此加密api与我的原始文件传输服务集成,在这里我可以获得源inputstream的句柄并将其提供给api请求,从api响应接收inputstream,然后将此插件到我的原始ioutils.copy调用中以将数据传输到目标:
Destination InputStream -> Encryption API -> Encrypted InputStream -> IOUtils.copy -> Destination OutputStream
为了最初实现加密api调用,我尝试构建一个客户机,并向fileinputstream提供信息,并将响应提取到fileoutputstream中。我试过apachehttpclient和springrestemplate。在这两种情况下,对于较小的文件,加密api都能正常工作,但是对于较大的文件,加密api只能接收部分数据,而且似乎卡在那里了。原始呼叫者(文件传输服务)没有得到任何响应,也挂起了。两种实现中的行为是相同的。
使用httpclient实现:
InputStream unencryptedInputStream = new FileInputStream("test-file");
HttpClient httpclient = HttpClients.createDefault();
URIBuilder builder = new URIBuilder("http://127.0.0.1:1234/encrypt/test-file");
HttpPost request = new HttpPost(builder.build());
request.setHeader("Content-Type", "application/octet-stream");
InputStreamEntity inputStreamEntity = new InputStreamEntity(unencryptedInputStream, 1064041488);
inputStreamEntity.setContentType("application/octet-stream");
inputStreamEntity.setChunked(true);
request.setEntity(inputStreamEntity );
HttpResponse response = httpclient.execute(request);
HttpEntity entity = response.getEntity();
InputStream encryptedInputStream = entity.getContent();
OutputStream os = new FileOutputStream("test-file.enc");
IOUtils.copy(encryptedInputStream, os);
使用spring resttemplate实现:
RestTemplate restTemplate = new RestTemplate();
InputStream unencryptedInputStream = new FileInputStream("test-file");
OutputStream encryptedOutputStream = new FileOutputStream("test-file.enc");
SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
requestFactory.setBufferRequestBody(false);
restTemplate.setRequestFactory(requestFactory);
RequestCallback requestCallback = new RequestCallback() {
@Override
public void doWithRequest(ClientHttpRequest clientHttpRequest) throws IOException {
clientHttpRequest.getHeaders().add("Content-type", "application/octet-stream");
clientHttpRequest.getHeaders().add("Accept", "application/octet-stream");
IOUtils.copy(unencryptedInputStream, clientHttpRequest.getBody());
}
};
ResponseExtractor<InputStream> responseExtractor = new ResponseExtractor<InputStream>() {
@Override
public InputStream extractData(ClientHttpResponse clientHttpResponse) throws IOException {
IOUtils.copy(clientHttpResponse.getBody(), encryptedOutputStream);
return clientHttpResponse.getBody();
}
};
restTemplate.execute("http://127.0.0.1:1234/encrypt/test-file", HttpMethod.POST, requestCallback, responseExtractor);
这两种情况都适用于小文件,但挂起在大文件上。我曾尝试将请求ioutils.copy Package 在一个“runnable”线程中,但仍然存在相同的问题。
暂无答案!
目前还没有任何答案,快来回答吧!