J'ai un appel de service Web via lequel les fichiers Zip peuvent être téléchargés. Les fichiers sont ensuite transmis à un autre service pour le stockage, la décompression, etc. Pour l'instant, le fichier est stocké sur le système de fichiers, puis un FileSystemResource est construit.
Resource zipFile = new FileSystemResource(tempFile.getAbsolutePath());
Je pourrais utiliser un ByteStreamResource afin de gagner du temps (la sauvegarde du fichier sur le disque n'est pas nécessaire avant le transfert) mais pour cela j'ai besoin de construire un tableau d'octets. En cas de fichiers volumineux, j'obtiendrai une erreur "OutOfMemory: Java heap space").
ByteArrayResource r = new ByteArrayResource(inputStream.getBytes());
Des solutions pour transférer des fichiers sans obtenir une erreur OutOfMemory en utilisant RestTemplate?
Vous pouvez utiliser execute
pour ce type d'opération de bas niveau. Dans cet extrait, j'ai utilisé la méthode copy
de Commons IO pour copier le flux d'entrée. Vous devrez personnaliser le HttpMessageConverterExtractor
pour le type de réponse que vous attendez.
final InputStream fis = new FileInputStream(new File("c:\\autoexec.bat")); // or whatever
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>(String.class, restTemplate.getMessageConverters());
restTemplate.execute("http://localhost:4000", HttpMethod.POST, requestCallback, responseExtractor);
(Merci à Baz d'avoir souligné que vous devez appeler setBufferRequestBody(false)
ou cela vaincra le point)
Je pense que la réponse ci-dessus contient du code inutile - vous n'avez pas besoin de créer une classe interne RequestCallback anonyme, et vous n'avez pas besoin d'utiliser IOUtils d'Apache.
J'ai passé un peu de temps à rechercher une solution similaire à la vôtre et voici ce que j'ai trouvé:
Vous pouvez atteindre votre objectif beaucoup plus simplement en utilisant l'interface de ressource Spring et RestTemplate.
RestTemplate restTemplate = new RestTemplate();
SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
requestFactory.setBufferRequestBody(false);
restTemplate.setRequestFactory(requestFactory);
File file = new File("/whatever");
HttpEntity<FileSystemResource> requestEntity = new HttpEntity<>(new FileSystemResource(file));
ResponseEntity e = restTemplate.exchange("http://localhost:4000", HttpMethod.POST, requestEntity, Map.class);
(Cet exemple suppose que la réponse à partir de laquelle vous postez est JSON. Mais, cela peut facilement être modifié en changeant la classe de type de retour ... définie sur Map.class ci-dessus)
La seule partie de @ artbristol réponse dont vous avez vraiment besoin est celle-ci (que vous pouvez configurer en tant que RestTemplate
Spring bean):
final RestTemplate restTemplate = new RestTemplate();
SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
requestFactory.setBufferRequestBody(false);
restTemplate.setRequestFactory(requestFactory);
Après cela, je pense que l'utilisation d'un FileSystemResource
comme corps de votre requête fera la bonne chose.
J'ai également utilisé un InputStreamResource
avec succès de cette façon, pour les cas où vous avez déjà les données en tant que InputStream
et n'avez pas besoin de les consommer plusieurs fois.
Dans mon cas, nous avions compressé nos fichiers et enveloppé un GZipInputStream
dans un InputStreamResource
.