【问题标题】:How to generate a downloadable PDF with pdfbox (Corrupted PDF)?如何使用 pdfbox(损坏的 PDF)生成可下载的 PDF?
【发布时间】:2012-02-13 08:33:49
【问题描述】:

如何使 PDF 文件在链接中可下载?

我正在使用 JSF 构建一个 Web 应用程序,当用户单击“另存为 PDF”链接时,应该可以下载一个 PDF。

到目前为止,我有一个生成 PDF 文件的工作代码,但该文件保存在我的桌面上,我想要做的是当用户单击链接时,应该可以下载 pdf 文件而不是存储该文件在应用程序中。

更新 3: 感谢你们的帮助,我根据你们的建议修改了我的代码,它正在工作。

更新 2: 我收到以下错误:Adoble Reader 无法打开“yourfile.pdf”,因为文件类型不受支持或文件已损坏

更新 1: 我正在添加我当前的代码以及您指出的更改,但是我仍在努力完成这项工作

这是我生成 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;
}

这是我的 servlet,它调用前面的代码并生成输出并设置标题:

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();
    }   

我不确定我错过了什么,因为当我尝试打开 PDF 时出现错误:Adoble Reader 无法打开“yourfile.pdf”,因为不是受支持的文件类型或文件已被损坏

【问题讨论】:

  • 重新“更新 2”,这可能是这个错误:issues.apache.org/jira/browse/PDFBOX-2026。它将在 1.8.5 中修复。或下载快照。
  • 你好@Night。我正在尝试实现与您完成的类似的事情。您能否将响应对象声明放入您的 servlet 中?或者可能发布整个代码?

标签: java web pdfbox


【解决方案1】:

我已经有一段时间没有这样做了,所以请耐心等待,但是您所做的不是通过流将 pdf 保存到文件中,而是将流作为字节数组保存在内存中,然后当用户单击时链接,您将 MIME 类型设置为 PDF,然后将字节数组作为流打开,作为响应返回。我很抱歉在细节上有点模糊。我想我也使用了 jpedal 和 iText 来完成它。

我无法向您展示所有代码,但这里有一些:

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;
}

然后,您可以使用正确的 MIME 类型将回复中的 baos 写为 pdf。

【讨论】:

  • 我根据您的回复使用修改后的代码版本更新了我的问题。
【解决方案2】:

您需要设置正确的 http 标头以便告诉浏览器下载文件。

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

【讨论】:

  • 我在我的问题中添加了一个示例代码,我还添加了标题,但在尝试打开 PDF 文件时出现以下错误:Adoble Reader 无法打开“yourfile.pdf”,因为不是支持的文件类型或文件已损坏。
  • “yourfile.pdf”应该是您正在生成的文件名。我只将其作为示例名称包含在内。尝试删除反斜杠和引号。
  • response.addHeader("Content-Disposition", "attachment; filename=yourFile.pdf")
  • 我仍在努力完成这项工作,我的意思是感谢您的回复和 Ben Brunk 的回复,现在我可以生成可下载的文件,但它似乎已损坏,可能问题出在我如何处理响应中的保存或输出流。
猜你喜欢
  • 2022-10-05
  • 1970-01-01
  • 1970-01-01
  • 2019-08-19
  • 1970-01-01
  • 1970-01-01
  • 2021-07-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多