0

I need to export PDF file by controller to an user. My REST is look like that however it returns empty file.

@RequestMapping(value="/pdfReport", method=RequestMethod.PUT, produces = MediaType.APPLICATION_JSON_VALUE)
public void downloadPDFReport(HttpServletResponse response, @RequestBody PDFReport pdfReport) throws IOException{

    StringBuilder sB = storageManager.getPDF(pdfReport);
    System.out.println(sB.toString());

    PDDocument document = new PDDocument();
    PDPage page = new PDPage();
    document.addPage(page);
    PDPageContentStream contentStream = new PDPageContentStream(document, page);
    contentStream.setFont(PDType1Font.TIMES_ROMAN, 12);
    contentStream.beginText();
    contentStream.showText(sB.toString());
    contentStream.endText();
    contentStream.close();

    document.save("pdfBoxHelloWorld.pdf");

    PDStream pdfStream = new PDStream(document);
    InputStream inputStream = pdfStream.createInputStream();
    FileCopyUtils.copy(inputStream, response.getOutputStream());
}

I print out StringBuilder so I am 100% sure that the content of StringBuilder is correct.

Tom
  • 303
  • 1
  • 4
  • 18

1 Answers1

4

Your code

PDStream pdfStream = new PDStream(document);
InputStream inputStream = pdfStream.createInputStream();
FileCopyUtils.copy(inputStream, response.getOutputStream());

does not make any sense, according to the JavaDocs of that PDStream constructor

/**
 * Creates a new empty PDStream object.
 * 
 * @param document The document that the stream will be part of.
 */
public PDStream(PDDocument document)

pdfStream is a new empty PDStream object which is part of document. Thus, it does not surprise at all that it returns empty file.

Consider using simply

document.save(response.getOutputStream());

instead.

Alternatively, if in your streaming context a content length property needs to be set before actually streaming the content, do something like this:

try (   ByteArrayOutputStream baos = new ByteArrayOutputStream()   )
{
    [...]
    doc.save(baos);
    byte[] bytes = baos.toByteArray();

    [... set response content length property to bytes.length ...]

    response.getOutputStream().write(bytes);
}
mkl
  • 90,588
  • 15
  • 125
  • 265
  • I would like to focus at the first part. It helps me to return .pdf however it is still empty. I changed my contentStream `contentStream.showText("Hello world");` – Tom Apr 09 '18 at 09:57
  • *"It helps me to return .pdf however it is still empty."* - Does this mean that a non-empty (length > 0) file is returned but only contains a blank page? Or does it mean that you still receive an empty file (length == 0)? In the former case please save the retrieved file and share it for analysis. In the latter case try setting the response content length property before streaming the data. – mkl Apr 09 '18 at 10:04
  • Yes it cointains blank page. It looks like the content is null. Here you can find pdf file which returns to me https://ufile.io/3gdao – Tom Apr 09 '18 at 10:10
  • The text is there, in the lower left corner, at the origin of the page coordinate system. Try adding `contentStream.newLineAtOffset(100, 600);` between `contentStream.beginText();` and `contentStream.showText("Hello world");` – mkl Apr 09 '18 at 10:25
  • Aww my bad. I was expecting content at the top of the page. Anyway when I change `contentStream.showText(sB.toString());` I have another problem `U+000A ('controlLF') is not available in this font Times-Roman encoding: WinAnsiEncoding`. I thought that it cause of '\n' and I am not sure how to fix it now. – Tom Apr 09 '18 at 10:32
  • Text drawing methods of PDFBox are very low-level. In particular they don't break text for you, neither at the end of line nor at control characters. You have to do all the layout'ing yourself, splitting text into lines and drawing them using separate method calls. You might want to look at [this answer](https://stackoverflow.com/a/19683618/1729265) for some example code for such tasks. – mkl Apr 09 '18 at 10:38
  • Do you know some better and free-use libraries for creating PDF? – Tom Apr 09 '18 at 10:58
  • I need to export to PDF reports contains of value and timestamp which are separated by ';' – Tom Apr 09 '18 at 11:01
  • Software recommendations strictly speaking are off-topic here and should be asked for on https://softwarerecs.stackexchange.com/ - iText would be the option on my mind but might not meet your definition of *free* (license is either AGPL or commercial, and AGPL might be to restrictive for you) – mkl Apr 09 '18 at 11:04