16

I came across a helpful PDF generation code to show the file to the client in a Spring MVC application ("Return generated PDF using Spring MVC"):

@RequestMapping(value = "/form/pdf", produces = "application/pdf")
public ResponseEntity<byte[]> showPdf(DomainModel domain, ModelMap model) {
    createPdf(domain, model);

    Path path = Paths.get(PATH_FILE);
    byte[] pdfContents = null;
    try {
        pdfContents = Files.readAllBytes(path);
    } catch (IOException e) {
        e.printStackTrace();
    }

    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.parseMediaType("application/pdf"));
    String filename = NAME_PDF;
    headers.setContentDispositionFormData(filename, filename);
    headers.setCacheControl("must-revalidate, post-check=0, pre-check=0");
    ResponseEntity<byte[]> response = new ResponseEntity<byte[]>(
            pdfContents, headers, HttpStatus.OK);
    return response;
}

I added a declaration that the method returns a PDF file ("Spring 3.0 Java REST return PDF document"): produces = "application/pdf".

My problem is that when the code above is executed, it immediately asks the client to save the PDF file. I want the PDF file to be viewed first in the browser so that the client can decide whether to save it or not.

I found "How to get PDF content (served from a Spring MVC controller method) to appear in a new window" that suggests to add target="_blank" in the Spring form tag. I tested it and as expected, it showed a new tab but the save prompt appeared again.

Another is "I can't open a .pdf in my browser by Java"'s method to add httpServletResponse.setHeader("Content-Disposition", "inline"); but I don't use HttpServletRequest to serve my PDF file.

How can I open the PDF file in a new tab given my code/situation?

Community
  • 1
  • 1

4 Answers4

27

Try

httpServletResponse.setHeader("Content-Disposition", "inline");

But using the responseEntity as follows.

HttpHeaders headers = new HttpHeaders();
headers.add("content-disposition", "attachment; filename=" + fileName)
ResponseEntity<byte[]> response = new ResponseEntity<byte[]>(
            pdfContents, headers, HttpStatus.OK);

It should work

Not sure about this, but it seems you are using bad the setContentDispositionFormData, try>

headers.setContentDispositionFormData("attachment", fileName);

Let me know if that works

UPDATE

This behavior depends on the browser and the file you are trying to serve. With inline, the browser will try to open the file within the browser.

headers.setContentDispositionFormData("inline", fileName);

Or

headers.add("content-disposition", "inline;filename=" + fileName)

Read this to know difference between inline and attachment

Community
  • 1
  • 1
Koitoer
  • 18,778
  • 7
  • 63
  • 86
  • Hello! I added `headers.add("content-disposition", "attachment; filename=" + fileName)` and it still asks for the PDF to be saved :( It didn't show the PDF file in a new browser tab (thank you for the edit, yes, I missed that one) –  Feb 19 '14 at 05:43
  • I added an update in my answer, try a shoot using inline insead of attachment – Koitoer Feb 19 '14 at 05:50
  • 2
    `headers.add("Content-Disposition", "inline;filename=" + fileName);` did the trick (without the other one). Thank you! –  Feb 19 '14 at 05:59
  • 1
    response.setHeader("Content-Disposition:inline", "attachment; filename="+filename); worked for IE – Loks Oct 01 '15 at 15:17
  • But how do you "encode" the `fileName` in `headers.add("content-disposition", "inline;filename=" + fileName)`? Because a `fileName` of `"x.txt"; attachment; filename*=UTF-8''trick.exe` will mess up with client's interpretation of HTTP headers – Xenos Apr 24 '18 at 12:01
  • I think you could try URLEncoder.encode(filename, "UTF-8") – Koitoer Apr 24 '18 at 17:02
  • @Koitoer Your answer is working fine ! But I want to stay existing tab when pdf is opening in new tab. Is there any way ?? – Avijit Barua Nov 20 '18 at 12:15
  • you guys have UI ? i tried xmlhttprequest to fetch blob then download but it fails. Even with inline! – Ash Jun 04 '22 at 03:46
1

SpringBoot 2

Use this code to display the pdf in the browser. (PDF in directory resources -> CLASSPATH) Using ResponseEntity<?>

    @GetMapping(value = "/showPDF")
public ResponseEntity<?> exportarPDF( ){        
    
    InputStreamResource file = new InputStreamResource(service.exportPDF());
    
    return ResponseEntity.ok()
            .header(HttpHeaders.CONTENT_DISPOSITION, "inline;attachment; filename=ayuda.pdf")
            .contentType(MediaType.APPLICATION_PDF)
            .body(file);            
}




@Service
public class AyudaServiceImpl implements AyudaService {
    private static final Logger LOGGER = LoggerFactory.getLogger(LoadPDF.class);
    
    LoadPDF  pdf = new LoadPDF();
    
    public InputStream exportPDF() {    
        LOGGER.info("Inicia metodo de negocio :: getPDF");                  
        return pdf.getPDF();
    }
}

---CLASE

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.ResourceUtils;


public class LoadPDF {
    
    private static final Logger LOGGER = LoggerFactory.getLogger(LoadPDF.class);
    public  InputStream getPDF(){        
               
        try {
            File file = ResourceUtils.getFile("classpath:ayuda.pdf");
            LOGGER.debug("Ruta del archivo pdf: [" + file + "]");
            InputStream in = new FileInputStream(file);
            LOGGER.info("Encontro el archivo PDF");
            return in;
        } catch (IOException e) {
            LOGGER.error("No encontro el archivo PDF",e.getMessage());
            throw new AyudaException("No encontro el archivo PDF", e ); 
        }
    }
}
natan barron
  • 61
  • 1
  • 2
0
/* Here is a simple code that worked just fine to open pdf(byte stream) file 
* in browser , Assuming you have a a method yourService.getPdfContent() that 
* returns the bite stream for the pdf file
*/

@GET
@Path("/download/")
@Produces("application/pdf")
public byte[] getDownload() {
   byte[] pdfContents = yourService.getPdfContent();
   return pdfContents;
}
mykey
  • 1,943
  • 19
  • 13
0

What happened is that since you "manually" provided headers to the response, Spring did not added the other headers (e.g. produces="application/pdf"). Here's the minimum code to display the pdf inline in the browser using Spring:

@GetMapping(value = "/form/pdf", produces = "application/pdf")
public ResponseEntity<byte[]> showPdf() {
    // getPdfBytes() simply returns: byte[]
    return ResponseEntity.ok(getPdfBytes());
}
Danilo Teodoro
  • 733
  • 5
  • 5