How to generate a downloadable PDF with pdfbox (Corrupted PDF)?

ぐ巨炮叔叔 提交于 2021-02-05 17:00:24

问题


How do I make a PDF file downloadable in a link?

I'm building a web application using JSF, when the user clicks in a "Save as PDF" link a PDF should be available to be downloaded.

So far I've a working code that generates the PDF file, but the file is saved on my desktop and what I want to do is that when the user clicks on the link the pdf file should be downloadable instead of being stored in the app.

UPDATE 3: Thank you for your help guys, I modifed my code with your suggestions and it's working.

UPDATE 2: I'm getting the following error: Adoble Reader could not open "yourfile.pdf" because is either not a supported file type or because the file has been damaged

UPDATE 1: I'm adding my current code with the changes you have pointed me out, however I'm still struggling to make this work

This is my method that generated the PDF:

public ByteArrayOutputStream createPDF() throws IOException, COSVisitorException {

    PDDocument document;
    PDPage page;
    PDFont font;
    PDPageContentStream contentStream;
    PDJpeg front;
    PDJpeg back;

    InputStream inputFront;
    InputStream inputBack;
    ByteArrayOutputStream output = new ByteArrayOutputStream(); 

    // Creating Document
    document = new PDDocument();

    // Creating Pages
    for(int i=0; i<2; i++) {

        page = new PDPage();

        // Adding page to document
        document.addPage(page); 

        // Adding FONT to document
        font = PDType1Font.HELVETICA;           

        // Retrieve Image to be added to the PDF
        inputFront = new FileInputStream(new File("D:/Media/imageFront.jpg"));  
        inputBack = new FileInputStream(new File("D:/Media/imageBack.jpg"));

        BufferedImage buffFront = ImageIO.read(inputFront);
        BufferedImage resizedFront = Scalr.resize(buffFront, 460);

        BufferedImage buffBack = ImageIO.read(inputBack);
        BufferedImage resizedBack = Scalr.resize(buffBack, 460); 

        front = new PDJpeg(document, resizedFront);
        back = new PDJpeg(document, resizedBack);

        // Next we start a new content stream which will "hold" the to be created content.
        contentStream = new PDPageContentStream(document, page);                

        // Let's define the content stream
        contentStream.beginText();
        contentStream.setFont(font, 8);
        contentStream.moveTextPositionByAmount(10, 770);
        contentStream.drawString("Amount: $1.00");
        contentStream.endText();

        contentStream.beginText();
        contentStream.setFont(font, 8);
        contentStream.moveTextPositionByAmount(200, 770);
        contentStream.drawString("Sequence Number: 123456789");
        contentStream.endText();

        contentStream.beginText();
        contentStream.setFont(font, 8);
        contentStream.moveTextPositionByAmount(10, 760);
        contentStream.drawString("Account: 123456789");
        contentStream.endText();

        contentStream.beginText();
        contentStream.setFont(font, 8);
        contentStream.moveTextPositionByAmount(200, 760);
        contentStream.drawString("Captura Date: 04/25/2011");
        contentStream.endText();

        contentStream.beginText();
        contentStream.setFont(font, 8);
        contentStream.moveTextPositionByAmount(10, 750);
        contentStream.drawString("Bank Number: 123456789");
        contentStream.endText();

        contentStream.beginText();
        contentStream.setFont(font, 8);
        contentStream.moveTextPositionByAmount(200, 750);
        contentStream.drawString("Check Number: 123456789");
        contentStream.endText();            

        // Let's close the content stream       
        contentStream.close();

    }

    // Finally Let's save the PDF
    document.save(output);
    document.close();

    return output;
}

This is my servlet that call the previous code and generates the output and set the header:

try {

        ByteArrayOutputStream output = new ByteArrayOutputStream();
        output = createPDF();

        response.addHeader("Content-Type", "application/force-download"); 
        response.addHeader("Content-Disposition", "attachment; filename=\"yourFile.pdf\"");
        response.getOutputStream().write(output.toByteArray());

    } catch (Exception ex) {            
        ex.printStackTrace();
    }   

I'm not sure what I'm missing since when I try to open the PDF I got the error: Adoble Reader could not open "yourfile.pdf" because is either not a supported file type or because the file has been damaged


回答1:


You need to set the proper http headers in order to tell the browser to download the file.

response.addHeader("Content-Type", "application/force-download")
response.addHeader("Content-Disposition", "attachment; filename=\"yourFile.pdf\"")



回答2:


I have not done this in awhile, so bear with me, but what you do is instead of saving the pdf to a file via a stream, you save the stream in memory as a byte array and then when the user clicks on the link, you set the MIME type to PDF and then open up the byte array as a stream which you return as the response. I apologize for being a bit hazy on details. I think I also used jpedal and iText to get it done.

I can't show you all of the code, but here is some:

import com.itextpdf.text.BaseColor;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.text.pdf.draw.DottedLineSeparator;

... // class, etc.

public ByteArrayOutputStream createOrderFormPdf(OrderFormDTO dto)
        throws DocumentException {
    Document document = new Document();
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    PdfWriter.getInstance(document, baos);
    document.open();

    Paragraph header = new Paragraph();
    header.add(new Phrase(...));

    OrderFormDtoPdfAdapter pdfAdapter = new OrderFormDtoPdfAdapter(dto);
    header.add(pdfAdapter.getPdfHeaderTable());

    document.add(header);

            ... // other code

    Paragraph footer = new Paragraph();
    footer.add(pdfAdapter.getPDFFooterTable());

    document.add(footer);
    Paragraph paragraph = new Paragraph();
    PdfTableUtils.addEmptyLine(paragraph, 2);

    document.add(paragraph);
    document.add(new DottedLineSeparator());

    document.close();

    return baos;
}

You can then write out the baos on your response as a pdf using the correct MIME type.



来源:https://stackoverflow.com/questions/8913259/how-to-generate-a-downloadable-pdf-with-pdfbox-corrupted-pdf

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!