java - PDFBox 创建仅包含屏幕内容的 PDF

标签 java pdf pdfbox

我想用 Java 创建 PDF(我更喜欢在这里使用 PDFBox,但这不是严格要求)。部分内容必须是

  • 在屏幕上可见
  • 打印时不可见

(把它想象成标题,它已经预先打印在纸上,但 PDF 的数字版本应该在屏幕上显示此标题,但不打印它)

我看到这篇文章,它展示了一个很好的内容示例,该内容仅打印但在屏幕上不可见: Create a watermark (pdf Optional Content) that shows only when printing using PDFBox

现在我需要完全相反:在屏幕上显示但不打印。我也尝试阅读chapter 8.11 of PDF-1.7 spec ,但未能按照我的要求创建 PDF(尝试使用“查看”和“事件”“查看”以及“查看”和“打印”的组合...)

PS:或者,一个满足要求的简单 PDF(在屏幕上显示 2 个单词,打印时只打印其中一个)肯定会有所帮助(并且可能就足够了),因为我认为我应该能够使用 PDFBox 重新创建必要的词典...

最佳答案

我自己设法找到了解决方案。基本上,这就是我所做的:

  1. 在屏幕上绘制我想要的所有内容
  2. 绘制一个白色矩形,即页面大小,仅在打印时可见
  3. 在屏幕和打印上绘制我想要的任何内容。

这里有一些代码:

/**
 * adds a group (aka Layer) to PDF document that is only visible when printing
 * 
 * @param document
 * @throws IOException
 */
private static void addPrintOnlyLayer(PDDocument document) throws IOException {
    /* kinda constants */
    COSName printName = COSName.getPDFName("Print");
    COSArray printCategory = new COSArray();
    printCategory.add(printName);
    COSDictionary printState = new COSDictionary();
    printState.setItem("PrintState", COSName.ON);
    /* kinda constants */

    PDDocumentCatalog catalog = document.getDocumentCatalog();
    PDOptionalContentProperties ocProps = catalog.getOCProperties();
    if (ocProps == null) {
        ocProps = new PDOptionalContentProperties();
        ocProps.setBaseState(BaseState.OFF);
        catalog.setOCProperties(ocProps);
    }

    COSDictionary ocPropsDict = (COSDictionary) ocProps.getCOSObject();
    COSDictionary dDict = ocPropsDict.getCOSDictionary(COSName.D);
    dDict.setItem(COSName.AS, new COSArray());

    PDOptionalContentGroup printOnlyGroup = null;
    if (ocProps.hasGroup(PRINT_ONLY_GROUP_NAME)) {
        printOnlyGroup = ocProps.getGroup(PRINT_ONLY_GROUP_NAME);
    } else {
        printOnlyGroup = new PDOptionalContentGroup(PRINT_ONLY_GROUP_NAME);
        ocProps.addGroup(printOnlyGroup);
    }

    COSDictionary printOnlyGroupDict = printOnlyGroup.getCOSObject();
    COSArray ocgs = new COSArray();
    ocgs.add(printOnlyGroupDict);

    COSDictionary usageDict = new COSDictionary();
    usageDict.setItem("Print", printState);

    printOnlyGroupDict.setItem("Usage", usageDict);

    COSDictionary asPrint = new COSDictionary();
    asPrint.setItem("Event", printName);
    asPrint.setItem("Category", printCategory);
    asPrint.setItem(COSName.OCGS, ocgs);

    dDict.getCOSArray(COSName.AS).add(asPrint);
}

/*** somewhere else ***/
PDDocument pdDoc = new PDDocument();
pdDoc.setVersion(1.7f);
addPrintOnlyLayer(pdDoc);
PDPage page = new PDPage(new PDRectangle(1000,2000));
pdDoc.addPage(page);

PDPageContentStream content = new PDPageContentStream(pdDoc, page);

/* add content that will only visible on screen */
content.set...
content.add...

/* add white rectangle covering everything that we had so far */        
content.beginMarkedContent(COSName.OC, pdDoc.getDocumentCatalog().getOCProperties().getGroup(PRINT_ONLY_GROUP_NAME));
// TODO: maybe get rect size from page dimensions dynamically
content.setNonStrokingColor(Color.WHITE);
content.addRect(0,0,1000,2000);// here, I know the size of my page
content.fill();
/* here, we could add more content that is visible ONLY on printer but NOT on screen */
content.endMarkedContent();

/* stroke around the page, so printing on larger paper will have a border */
/* drop later */
content.addRect(0,0,1000,2000);
content.stroke();

/* now add content that will be visible on the print out AND screen */
content.set...;
content.add...;

/* close content of page */
content.close();

关于java - PDFBox 创建仅包含屏幕内容的 PDF,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58751013/

相关文章:

java - 获取异常-java.lang.IllegalStateException : Error: drawImage is not allowed within a text block

android - 将库添加到 eclipse

java - 如果我有一个 Runnable 和一个实现线程的对象,我该如何使用 wait() 和 notification() ?

java - 正则表达式的组计数问题

java - java fork-join 框架如何将任务分配到处理器上?

ios - 将 NSURL 的 PDF 保存在本地 - 检索

javascript - 将 PDF 转换为 PNG Node.JS

PDF 中的 Java 数据

java - 使用 int + ""是否不利于将 Java int 转换为字符串?

java - 如何(水平)对齐 PDFBox 中 PDTextField 的文本?