Jakub S.
Jakub S.

Reputation: 628

Set the Content-Type header dynamically in Spring Boot

I have a controller method that serves a file decoded from a Base64 string.

// Simplified from original
@GetMapping("/download/{id}")
public byte[] download(@PathVariable String id, HttpServletResponse response) throws Exception {
    var doc = new Document("test.pdf", "application/pdf", "Base64 encoded data"); // This is loaded from elsewhere

    response.addHeader("Content-Type", doc.getType());
    response.addHeader("Content-Disposition", "attachment; filename=\"%s\"".formatted(doc.getFilename()));

    return Base64.getDecoder().decode(doc.getData());
}

When I set the header through HttpServletResponse, Spring seems to always override it to text/html. I can't set it with an annotation or configuration because I need to set it dynamically inside the controller method.

How do I set the Content-Type header dynamically without Spring overriding it?

Upvotes: 1

Views: 6073

Answers (1)

mentallurg
mentallurg

Reputation: 5207

Use ResponseEntity as a return type instead of manipulating the Response. The code can look as follows:

@GetMapping("/download/{id}")
public ResponseEntity<byte[]> download(@PathVariable String id) throws Exception {
    var doc = new Document("test.pdf", "application/pdf", "Base64 encoded data");

    HttpHeaders headers = new HttpHeaders();
    headers.add("Content-Type", doc.getType());
    headers.add("Content-Disposition", "attachment; filename=\"%s\"".formatted(doc.getFilename()));

    return ResponseEntity
        .status(HttpStatus.OK)
        .headers(headers)
        .body(Base64.getDecoder().decode(doc.getData()));
}

You can also simplify setting of headers. Instead of using headers names

    headers.add("Content-Type", doc.getType());

you can use methods

    headers.setContentType(doc.getType());

Upvotes: 4

Related Questions