3

I am developing a rest controller to download a .docx file into the client system. My code is working fine as the file is getting downloaded. Now I want to enhance the response. My requirement is to also send a JSON payload in the response along with the .docx file content, something like

{"message":"Report downloaded Successfully"}

incase of successful download or with a different message incase of failure.

Below is my restcontroller code:

@RestController
public class DownloadController {
    
    
    @PostMapping(value="/download",
            consumes = {"multipart/form-data"},
            produces = {"application/octet-stream"})
    public ResponseEntity<?> downloadFile(@RequestParam("file") MultipartFile uploadFile){
        
        //business logic to create the attachment file
        
        try {
            
            File file = new File("path_to_.DOCX file_I_have_created");
            byte[] contents = Files.readAllBytes(Paths.get(file.getAbsolutePath()));
            
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
            headers.setContentDisposition(ContentDisposition.attachment().filename("survey.docx").build());
            
            return new ResponseEntity<>(contents, headers, HttpStatus.OK);
        } catch (Exception e){
            return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }

}

How do I modify my response code to send both the JSON message and the byte[] contents so that the file gets downloaded and I can see the JSON message in the response preview tab in the chrome or response body in postman?

UPDATE: I tried to define a response class like below

public class Downloadresponse {

private byte[] content;
private String message;

//getter,setters

}

With this change in place, I am getting below exception:

Resolved [ HttpMessageNotWritableException: No converter for [class ...Downloadresponse] with preset content-type "application/octet-stream”]

3 Answers 3

2

You can't. HTTP doesn't allow you to defined multiple content-types on 1 request/response. That being said, you could send the byte array base64 encoded as part of a json response but would need to handle it in the front-end (if you have any) as it would not trigger the file download process of the browser.

Sign up to request clarification or add additional context in comments.

Comments

1

You can define custom class which hold your current content and message . So you can return that class in the response

ResponseClass
{
byte[] contents;
String message;
}

4 Comments

I tried it. It didn't work.
then you can add this message into header like below String msg="Report downloaded Successfully"; headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); headers.put("message", Collections.singletonList(msg));
Hi Dhiraj, while I try the solution of putting headers.put("message", Collections.singletonList(msg)); could you please see the update to my question about the exception I am getting. Any idea on how to solve that issue?
Another way todo is you can store the message into file and return that file in the response . So response will have 2 files .
0

You can send a json object that contain the message and the file as encoded64 string.

And in the client side you decode it and download it.

public record MyRecord(String message, String encodedStringBase64, String filename) {}


...

try {
        
        File file = new File("path_to_.DOCX file_I_have_created");
        byte[] contents = Files.readAllBytes(Paths.get(file.getAbsolutePath()));
        String encodedString = Base64.getEncoder().encodeToString(contents);
     
        MyRecord record = new MyRecord("Report downloaded Successfully", encodedString, file.getName());

        return log.traceExit(ResponseEntity.ok().headers(headers)
                .contentType(MediaType.valueOf("application/json")).body(record));
} ...

1 Comment

here an example how to download it in JS Gist Github

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.