简体   繁体   中英

How to programmatically consume a file from a Rest API using Spring?

I have the following Rest resource which downloads a file from DB. It works fine from the browser, however, when I try to do it from a Java client as below, I get 406 (Not accepted error).

...
 @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 different port (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?

The response code is 406 Not Accepted. You need to specify an 'Accept' request header which must match the 'produces' field of your RequestMapping.

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: don't do this for large files. RestTemplate.exchange(...) always loads the entire response into memory, so you could get OutOfMemory exceptions. To avoid this, do not use Spring RestTemplate, but rather use the Java standard HttpUrlConnection directly or apache http-components.

maybe try this, change your rest 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 download 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 tell it where to save the file, the REST API won't do that for you I don't think.

You may 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)));
    }
}

Use this for downloading an JPEG image using exchange. This works perfect.

URI uri = new URI(packing_url.trim());

HttpHeaders headers = new HttpHeaders();
headers.setAccept(Arrays.asList(MediaType.IMAGE_JPEG));
HttpEntity<String> entity = new HttpEntity<String>("parameters", headers);

// Send the request as GET
ResponseEntity<byte[]> result= template.exchange(uri, HttpMethod.GET, entity, byte[].class);

out.write(result.getBody());

尝试使用RestTemplate上的execute方法和ResponseExtractor,并使用提取器从流中读取数据。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM