当前位置: 首页 > 知识库问答 >
问题:

PDFBox创建具有仅屏幕内容的PDF

公孙栋
2023-03-14

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

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

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

我看到了这篇文章,它展示了一个很好的内容示例,即仅打印但在屏幕上不可见:创建一个仅在使用PDFBox打印时显示的水印(pdf可选内容)

现在我需要完全相反的:在屏幕上显示但不打印。我还尝试阅读PDF-1.7规范的第8.11章,但无法按照我的要求创建PDF(使用“视图”和“事件”视图以及“视图”和“打印”的组合...)

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

共有1个答案

慕弘义
2023-03-14

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

  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();
 类似资料:
  • 我需要创建一个上传文件的预览。问题:文件将是360°全景,我使用pannellum作为显示库。因此,我在debian服务器上安装了Pagers,上传后,我只需执行以下PHP行: 它绝对是伟大的作品!我得到了一个完美的截图。不幸的是(和预期的一样),这只是一个消息,WebGL不支持此设备...:( 我搜索了Stackoverflow,用谷歌搜索了一下。不幸的是,没有有用的想法。因此,我需要一位专家(

  • 我正在开发PDF Toc。它会生成第一页,但当我有更多元素时,我会逻辑地为TOC创建一个新页面。我正在使用PDF Box和那个PDPageContentStream。我必须创建一个函数来计算我需要多少页面。然后我在列表中创建确切数量的页面,并在我启动PDPageContentStream之前将它们添加到PDF文档中。该流处于循环中,它只生成第一页。其他页面是空白的。我不知道到底出了什么问题。这是代

  • 我遇到过许多使用PDFBox Layer实用程序的appendFormAsLayer方法的示例,如下所示: 前面代码中的getPDFName调用中的“mc”有什么意义? 我已经编写了下面的代码,在一个现有pdf的每一页上插入水印,并启用每一组可选内容。 将组设置为已启用或已禁用的“SetGroupEnabled(groupName,true)”将使其显示以供显示和打印。根据我在这个主题上研究的其他

  • 就像上面提到的图像一样。但我将背景色黑色添加到默认,红色添加到19201080。对于19201080个像素分辨率不带红色的模拟器,我这样做是为了在Android中为不同的屏幕尺寸创建不同的UI

  • 我使用HTML2Canvas渲染两个反应组件,问题是文档的输出只呈现屏幕上可见的内容,所以如果组件的内容很短,我可以看到pdf中的所有内容,但是,如果内容很长,我需要滚动到页面的顶部,使其工作,或者我需要将我的导航缩放到50%,然后单击print 我的代码中是否有错误:

  • 我正在尝试做一个像Instagram的UI来练习。当我添加一个NavigationView时,它会在屏幕的四个边创建一个空边框。下面是UI的样子- 下面是我的代码。我可能做错了什么?