How to programmatically use a file from the Rest API using Spring?

I have the following Rest resource that loads a file from the database. It works fine in the browser, however, when I try to do this using the Java client as shown below, I get 406 (error not accepted).

... @RequestMapping(value="/download/{name}", method=RequestMethod.GET, produces = MediaType.APPLICATION_OCTET_STREAM_VALUE) public @ResponseBody HttpEntity<byte[]> downloadActivityJar(@PathVariable String name) throws IOException { logger.info("downloading : " + name + " ... "); byte[] file = IOUtils.toByteArray(artifactRepository.downloadJar(name)); HttpHeaders header = new HttpHeaders(); header.set("Content-Disposition", "attachment; filename="+ name + ".jar"); header.setContentLength(file.length); return new HttpEntity<byte[]>(file, header); } ... 

The client is deployed on the same server with a different port (the message gives the correct name):

  ... RestTemplate restTemplate = new RestTemplate(); String url = "http://localhost:8080/activities/download/" + message.getActivity().getName(); File jar = restTemplate.getForObject(url, File.class); logger.info("File size: " + jar.length() + " Name: " + jar.getName()); ... 

What am I missing here?

+6
source share
4 answers

The 406 response code is not accepted. You need to specify the “Accept” request header, which should correspond to the “produces” field of your RequestMapping template.

 RestTemplate restTemplate = new RestTemplate(); restTemplate.getMessageConverters().add(new ByteArrayHttpMessageConverter()); HttpHeaders headers = new HttpHeaders(); headers.setAccept(Arrays.asList(MediaType.APPLICATION_OCTET_STREAM)); HttpEntity<String> entity = new HttpEntity<String>(headers); ResponseEntity<byte[]> response = restTemplate.exchange(URI, HttpMethod.GET, entity, byte[].class, "1"); if(response.getStatusCode().equals(HttpStatus.OK)) { FileOutputStream output = new FileOutputStream(new File("filename.jar")); IOUtils.write(response.getBody(), output); } 

A small warning: do not do this for large files. RestTemplate.exchange (...) always loads the entire response into memory, so you can get OutOfMemory exceptions. To avoid this, do not use Spring RestTemplate, but rather use the Java HttpUrlConnection directly or the apache http components.

+15
source

maybe try this, change your resting method as such:

 public javax.ws.rs.core.Response downloadActivityJar(@PathVariable String name) throws IOException { byte[] file = IOUtils.toByteArray(artifactRepository.downloadJar(name)); return Response.status(200).entity(file).header("Content-Disposition", "attachment; filename=\"" + name + ".jar\"").build(); } 

Also, use something like this to upload the file, you are doing it wrong.

 org.apache.commons.io.FileUtils.copyURLToFile(new URL("http://localhost:8080/activities/download/" + message.getActivity().getName()), new File("locationOfFile.jar")); 

You need to specify where to save the file, the REST API will not do this for you, I do not think so.

+2
source

You can use InputStreamResource with ByteArrayInputStream.

 @RestController public class SomeController { public ResponseEntity<InputStreamResource> someResource() { byte[] byteArr = ...; return ResponseEntity.status(HttpStatus.OK).body(new InputStreamResource(new ByteArrayInputStream(byteArr))); } } 
+1
source

Try using the execute method on the RestTemplate with a ResponseExtractor and read the data from the stream using an extractor.

0
source

Source: https://habr.com/ru/post/977362/


All Articles