Spring REST returning PDF - Response status 406 (not acceptable)
18,905
Basically there is no need to add produces = "application/pdf"
in RequestMapping as it seems to try to convert the ResponeBody internally. You can just add MediaType
to response headers which is what you need.
@ResponseBody
@RequestMapping(value = "get/pdf/{id}", headers="Accept=*/*", method = RequestMethod.GET)
public ResponseEntity<InputStreamResource> getPdfContractById(@PathVariable("id") Long id){
// Get the remove file based on the fileaddress
RemoteFile remotefile = new RemoteFile(id);
// Set the input stream
InputStream inputstream = remotefile.getInputStream();
// asume that it was a PDF file
HttpHeaders responseHeaders = new HttpHeaders();
InputStreamResource inputStreamResource = new InputStreamResource(inputStream);
responseHeaders.setContentLength(contentLengthOfStream);
responseHeaders.setContentType(MediaType.valueOf("application/pdf"));
// just in case you need to support browsers
responseHeaders.put("Content-Disposition", Collections.singletonList("attachment; filename=somefile.pdf"))
return new ResponseEntity<InputStreamResource> (inputStreamResource,
responseHeaders,
HttpStatus.OK);
}
Comments
-
Manu almost 2 years
I read many questions on SO about this type of issue, but all of them recommend using the correct Jackson version. This is my current situation:
REST API:
@RequestMapping(value = "get/pdf/{id}", headers="Accept=*/*", method = RequestMethod.GET, produces = "application/pdf") @Override public ResponseEntity<InputStream> getPdfContractById(@PathVariable("id") Long id);
Using
Accept:*/*
produces an error in mapping the request (404 occurs)From my pom:
<dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>2.4.1</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.4.1.1</version> </dependency>
I also tried to add these two dependencies, but nothing changes:
<dependency> <groupId>org.codehaus.jackson</groupId> <artifactId>jackson-core-asl</artifactId> <version>1.9.13</version> </dependency> <dependency> <groupId>org.codehaus.jackson</groupId> <artifactId>jackson-mapper-asl</artifactId> <version>1.9.13</version> </dependency>
Response client-side:
There was an unexpected error (type=Not Acceptable, status=406).
Headers incude:Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 Accept-Encoding:gzip, deflate, sdch
What's wrong with it?
More detailsI am using this code to return the remote PDF file:
URL url = null; try { url = new URL(urlStr); } catch (MalformedURLException e) { e.printStackTrace(); throw new MyException(e.getMessage()); } InputStream pdfFile = null; try { pdfFile = url.openStream(); } catch (IOException e) { e.printStackTrace(); throw new MyException(e.getMessage()); } ResponseEntity<InputStream> re = ResponseEntity .ok() // .headers(headers) // .contentLength(contentLength) .contentType( MediaType.parseMediaType("application/pdf")) .body(pdfFile); return re;
-
Manu over 8 yearsThanks for your answer. I update my OP and I added the code I am using. It is very similar, but I cannot use an InputStreamResource (my input stream has already been read). That does not seem to work, though.
-
Babl over 8 yearsHave you removed
produces
from RequestMapping ? And where is your stream read ? I dont see why you can't use InputStream Reader, but if you can, just try to return an byte[] in reponse, see if it works ... -
Manu over 8 yearsI did remove it. If I return an InputStreamReader, I get a 500 error saying that the input stream has already been read.
-
Babl over 8 yearsSo lets try the things which I suggested, remove produces, and if not return the byte[] in reponse entity.
-
Manu over 8 yearsGreat! Returning the byte array solves the problem. Also, I am not using 'produces' in the RequestMapping annotation and there is no need to add Jackson dependencies.
-
Manu over 8 yearsThe only thing I would like now is that the file should not be opened, but rather download with a name I want to choose.
-
Babl over 8 yearsJust add ("Content-Disposition", "attachment; filename=somefile.pdf") header
-
Sabir Khan over 5 years@Babl : How you calculated
contentLengthOfStream
? -
Babl over 5 years@SabirKhan basically you can not calculate the content length of the stream without fully going over it, but in most of the cases, the system by its own has that data. Say someone has uploaded the file, the system can store the content length in some DB and read it from there. Otherwise, you will need to read the full stream to get its length.