ddd ddd - 7 months ago 31
Java Question

HTTP 406 downloading a file with rest call

I followed this tutorial to implement rest API with Spring Boot for downloading files (xml format).

My controller class is as follows:

@RestController
public class RistoreController {
@Autowired
private RistoreService ristoreService;

@RequestMapping(
value = "/ristore/foundation/{trf}",
method = RequestMethod.GET,
produces = "application/xml")
public ResponseEntity<InputStream> getXMLById(@PathVariable("trf") String trf) throws IOException {
InputStream inputStream = ristoreService.findByTRF(trf);
return ResponseEntity
.ok()
.contentType(MediaType.parseMediaType("application/octet-stream"))
.body(inputStream);
}
}


I have service interface
RistoreService
autowired in the controller and Bean class for that service looks like this:

@Service
public class RistoreServiceBean implements RistoreService {
public InputStream findByTRF(String trf) throws IOException {
String filePath = "/Users/djiao/Box Sync/Work/Projects/RIStore/foundation/foundation_new/" + trf + ".xml";
File file = new File(filePath);
return new FileInputStream(file);
}
}


I tested the application using the following curl command:

curl -i -H "Accept: application/xml" http://localhost:8080/ristore/foundation/TRF133672_1455294493597


However, I got 406 error, "Not Acceptable". Something wrong with the file format?

Answer

Try to change the definition of the controller that way

        @RequestMapping(value = "/ristore/foundation/{trf}", method = RequestMethod.GET, produces = "application/xml")
    public ResponseEntity<InputStreamResource> downloadXMLFile(@PathVariable("trf") String trf)
            throws IOException {

        // Optinal headers configuration 

HttpHeaders headers = new HttpHeaders();

        headers.add("Cache-Control", "no-cache, no-store, must-revalidate");
        headers.add("Pragma", "no-cache");
        headers.add("Expires", "0");


        // get the inputStream

    InputStream xmlFileInputStream = ristoreService.findByTRF(trf);



        return ResponseEntity
                .ok()
                .headers(headers)
                .contentType(MediaType.parseMediaType("application/octet-stream"))
                .body(new InputStreamResource(xmlFileInputStream));
    }

Then your service class would be :

 @Service
public class RistoreServiceBean implements RistoreService {
    public InputStream findByTRF(String trf) throws IOException {
        String filePath = "/Users/djiao/Box Sync/Work/Projects/RIStore/foundation/foundation_new/" + trf + ".xml";
        File file = new File(filePath);
        return new FileInputStream(file);
    }
}

406 Not Acceptable The resource identified by the request is only capable of generating response entities which have content characteristics not acceptable according to the accept headers sent in the request.

That means that the inputstream you return must be considered as a resource as soon as you have a REST controller.