Search code examples
javaspring-bootitext

Download not working from the response on Spring Boot


I can't download from the response. I don't know what I'm doing wrong. I tried changing content-type to octet-stream, application/pdf, tried not using "produces". If i write it locally instead of downloading, it generates the pdf perfectly. But if i'm trying to download from the response, it doesnt work.

I also tried in multiple browsers just to be sure and that's definitely not the case. Network tab on chrome shows that content-type and content-disposition are correct (at least correct like i'm asking it to be)

Is there something wrong with my code?

This is my Controller


@RestController
@RequestMapping("/api/pdf")
public class PdfController {

    private final PdfService pdfService;

    PdfController(PdfService pdfService) {
        this.pdfService = pdfService;
    }

    @PostMapping(value = "/generate", produces = MediaType.APPLICATION_PDF_VALUE)
    public ResponseEntity<InputStreamResource> createPdf(@RequestBody PendenciasModel pendenciasModel) throws IOException {
        try {
            ByteArrayInputStream bis = pdfService.createPdf(pendenciasModel);


        HttpHeaders headers = new HttpHeaders();
        headers.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_PDF_VALUE);
        headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename="+ pendenciasModel.getClient().getCpf() +".pdf");
        return ResponseEntity.ok().headers(headers)
                .body(new InputStreamResource(bis));
        }catch(IOException e){
            e.printStackTrace();
            return ResponseEntity.badRequest().body(null);
        }
    }


}


Solution

  • package com.example.demoDownloadPDF;
    
    import org.springframework.core.io.FileSystemResource;
    import org.springframework.core.io.InputStreamResource;
    import org.springframework.http.HttpHeaders;
    import org.springframework.http.HttpStatus;
    import org.springframework.http.MediaType;
    import org.springframework.http.ResponseEntity;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.RequestBody;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    import java.io.ByteArrayInputStream;
    import java.io.File;
    import java.io.IOException;
    import java.nio.file.NoSuchFileException;
    import java.util.Map;
    import java.nio.file.Files;
    import java.nio.file.Paths;
    
    
    
    @RestController
    @RequestMapping("/api/pdf")
    public class PdfController {
    /*
        private final PdfService pdfService;
    
        PdfController(PdfService pdfService) {
            this.pdfService = pdfService;
        }
      */
    
        @PostMapping(value = "/generate")
        //public ResponseEntity<InputStreamResource> createPdf(@RequestBody PendenciasModel pendenciasModel) throws IOException {
        public ResponseEntity<InputStreamResource> createPdf(@RequestBody Map<String, String> request)  throws IOException {
            try {
                String fileName = request.get("fileName");
                String filePath = "/home/demo/Downloads/Examples/demoDownloadPDF/pdfs/" + fileName;
                System.out.println("filePath =" + filePath);
                File file = new File(filePath);
                FileSystemResource resource = new FileSystemResource(file);
                byte[] pdfContent;
                pdfContent = Files.readAllBytes(Paths.get(filePath));
                ByteArrayInputStream bis = new ByteArrayInputStream(pdfContent);
                //ByteArrayInputStream bis = pdfService.createPdf(pendenciasModel);
    
    
    
                HttpHeaders headers = new HttpHeaders();
                //headers.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_PDF);
                headers.setContentType(MediaType.APPLICATION_PDF);
                //headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + pendenciasModel.getClient().getCpf() + ".pdf");
                headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + fileName);
    
                return ResponseEntity.ok().headers(headers).body(new InputStreamResource(bis));
                //return new ResponseEntity<>(new InputStreamResource(bis), headers, HttpStatus.OK);
            } catch (NoSuchFileException e) {
                System.err.println("NoSuchFileException>>>" + e.getMessage());
                //e.printStackTrace();
                return new ResponseEntity<>(HttpStatus.NOT_FOUND);
            } catch (IOException e) {
                System.err.println("IOException>>>"+e.getMessage());
                //e.printStackTrace();
                //return ResponseEntity.badRequest().body(null);
                return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
            }
        }
    }
    
    

    Test File

    put pdf files under /home/demo/Downloads/Examples/demoDownloadPDF/pdfs/

    ex: demo1.pdf , demo2.pdf , demo3.pdf

    Test

    compile

    mvn clean package 
    

    run

    java -jar target your-spring-boot.jar
    

    test

    curl -X POST -H "Content-Type: application/json" -d '{"fileName": "demo1.pdf"}' -o demo1.pdf http://localhost:8080/api/pdf/generate
    
    
    curl -X POST -H "Content-Type: application/json" -d '{"fileName": "demo100.pdf"}' -o demo100.pdf http://localhost:8080/api/pdf/generate
    

    Summary

    Because I don't know some of the categories you use, I can only simulate it. The above code can download the pdf file normally. The difference is that I am reading a fixed file. You should be able to easily change it to your writing method. Because I have preserved all your writing methods with comments.

    Your code: @RequestBody PendenciasModel pendenciasModel My Test: @RequestBody Map<String, String> request

    Your code:

    ByteArrayInputStream bis = pdfService.createPdf(pendenciasModel);

    My Test:

    byte[] pdfContent;
    pdfContent = Files.readAllBytes(Paths.get(filePath));
    ByteArrayInputStream bis = new ByteArrayInputStream(pdfContent);
    

    Your Code:

    headers.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_PDF);

    My Test:

    headers.setContentType(MediaType.APPLICATION_PDF);

    Your Code:

    headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + pendenciasModel.getClient().getCpf() + ".pdf");

    My Test:

    headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + fileName);

    Your Code:

    return ResponseEntity.badRequest().body(null);

    My Test:

    return new ResponseEntity<>(HttpStatus.BAD_REQUEST);

    I am test and run my code ok.