2016-12-09 3 views
1

Ich habe eine Rest API in einem Spring zum Generieren und Herunterladen einer PDF-Datei. Der Controller definitation ist wie folgt -Spring - Fehlermeldung kann nicht gesendet werden API API ByteArrayResource

@RequestMapping(
     value = "/foo/bar/pdf", 
     method = RequestMethod.GET, 
     produces = MediaType.APPLICATION_OCTET_STREAM_VALUE) 
@ResponseBody 
@Nullable 
public ByteArrayResource downloadPdf(@RequestParam int userId) { 
    byte[] result = null; 
    ByteArrayResource byteArrayResource = null; 

    result = service.generatePdf(userId); 

    if (result != null) { 
     byteArrayResource = new ByteArrayResource(result); 
    } 

    return byteArrayResource; 
} 

I Jackson für JSON Handhabung JSON verwenden und haben eine Exception-Handler ControllerAdvice. Das Problem ist, wenn diese API eine Ausnahme generiert und ich eine benutzerdefinierte Ausnahmeklasse (enthält Nachricht und ein zusätzliches Feld) zurückgibt.

Wie ich bereits produces = MediaType.APPLICATION_OCTET_STREAM_VALUE angegeben habe, wird diese benutzerdefinierte Klasse auch versucht, von Spring in einen Oktettstrom konvertiert zu werden, bei dem es fehlschlägt und HttpMediaTypeNotAcceptableException: Could not find acceptable representation produziert.

Ich versuchte Lösungen auf this Stackoverflow Frage, insbesondere this answer, aber es schlägt immer noch fehl. Diese Lösung schlägt zusammen mit anderen Änderungen vor, produces Teil aus @RequestMapping zu entfernen, aber wenn ich in AbstractMessageConverterMethodProcessor.getProducibleMediaTypes debuggte, erkennt es nur Anwendung/JSON als verfügbaren Antwortmedientyp.

tl; dr Wie kann ich diese API die Datei bei Erfolg zurückgeben und benutzerdefinierte JSON-Darstellung benutzerdefinierte Ausnahme Klasse bei Fehler zurückgegeben.

Antwort

1

Versuchen implementiert Ihre Aktion als

@RequestMapping(
    value = "/foo/bar/pdf", 
    method = RequestMethod.GET) 
@ResponseBody 
public HttpEntity<byte[]> downloadPdf(@RequestParam int userId) { 
byte[] result = service.generatePdf(userId); 

HttpHeaders headers = new HttpHeaders(); 

if (result != null) { 
    headers.setContentType(new MediaType("application", "pdf")); 
    headers.set("Content-Disposition", "inline; filename=export.pdf"); 
    headers.setContentLength(result.length); 

    return new HttpEntity(result, headers); 
} 

return new HttpEntity<>(header) 
} 

über die Ausnahmebehandlung zum Beispiel Sie YourCustomError und in Controller kommentierte mit @ControllerAdvice annotate ein Verfahren mit @ExceptionHandler(YourCustomError.class) und der Arbeit mit ihm werfen können.

0

Ich hatte das gleiche Problem mit ähnlichen Code. Ich entfernte gerade das produces Attribut von meinem @PostMapping und ich war in der Lage, die Datei oder das json zurückzukehren (wenn der api einige Fehler hat):

@Override 
@PostMapping 
public ResponseEntity<InputStreamResource> generate(
     @PathVariable long id 
) { 
    Result result = service.find(id); 

    return ResponseEntity 
      .ok() 
      .cacheControl(CacheControl.noCache()) 
      .contentLength(result.getSize()) 
      .contentType(MediaType.parseMediaType(MediaType.APPLICATION_PDF_VALUE)) 
      .body(new InputStreamResource(result.getFile())); 
} 

Wenn einige Fehler auftreten, hatte ich einen @ExceptionHandler davon zu kümmern :

@ExceptionHandler 
public ResponseEntity<ApiErrorResponse> handleApiException(ApiException ex) { 
    ApiErrorResponse error = new ApiErrorResponse(ex); 
    return new ResponseEntity<>(error, ex.getHttpStatus()); 
} 
Verwandte Themen