- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我们正在尝试使用主要由 "template"文件 形成的 iText 生成文档 - 使用 PdfContentByte.addTemplate
方法将较小的 PDF 文件组合成一个复合文件.我们然后使用 *nix 命令 lp
自动且静默地打印新文件。这通常有效;但是偶尔,生成的一些文件将打印失败。文档通过所有队列并到达打印机本身(在本例中为 Lexmark T652n),它的物理显示器给出了待处理进度的消息,甚至它的机械部件也开始准备 - 然后,打印作业自发消失而没有一个痕迹,打印机恢复准备就绪。
这个问题的具体程度很奇怪。对于初学者来说,当通过 Adobe PDF Viewer 手动完成时,有问题的文件打印不会失败,并且可以被 Adobe Live Cycle 等编辑器很好地阅读。此外,文件的内容影响它是否受到此问题的困扰,但不是以明确的方式 - 添加特定模板 20 次可能会导致问题,而添加 19 或 21 次可能是很好,或者使用不同的模板将完全改变模式,并可能导致它在 37 次后发生。生成具有完全相同内容的文档将在问题是否发生方面保持一致,但任何细微且看似无关的内容更改都会改变问题是否发生。
虽然这可能被认为是硬件问题,但事实仍然是某些 iText 生成的文件存在此问题,而其他文件则没有。 我们的文件创建方法是否有时创建的文件以某种方式被认为仅对打印机损坏,而且只是有时?
这里是一个相对较小的代码示例,它使用类似于我们的主程序的重复模板方法来生成文档。它使用 this file 作为模板并重复指定的次数。
public class PDFFileMaker {
private static final int INCH = 72;
final private static float MARGIN_TOP = INCH / 4;
final private static float MARGIN_BOTTOM = INCH / 2;
private static final String DIREC = "/pdftest/";
private static final String OUTPUT_FILEPATH = DIREC + "cooldoc_%d.pdf";
private static final String TEMPLATE1_FILEPATH = DIREC + "template1.pdf";
private static final Rectangle PAGE_SIZE = PageSize.LETTER;
private static final Rectangle TEMPLATE_SIZE = PageSize.LETTER;
private ByteArrayOutputStream workingBuffer;
private ByteArrayOutputStream storageBuffer;
private ByteArrayOutputStream templateBuffer;
private float currPosition;
private int currPage;
private int formFillCount;
private int templateTotal;
private static final int DEFAULT_NUMBER_OF_TIMES = 23;
public static void main (String [] args) {
System.out.println("Starting...");
PDFFileMaker maker = new PDFFileMaker();
File file = null;
try {
file = maker.createPDF(DEFAULT_NUMBER_OF_TIMES);
}
catch (Exception e) {
e.printStackTrace();
}
if (file == null || !file.exists()) {
System.out.println("File failed to be created.");
}
else {
System.out.println("File creation successful.");
}
}
public File createPDF(int inCount) throws Exception {
templateTotal = inCount;
String sFilepath = String.format(OUTPUT_FILEPATH, templateTotal);
workingBuffer = new ByteArrayOutputStream();
storageBuffer = new ByteArrayOutputStream();
templateBuffer = new ByteArrayOutputStream();
startPDF();
doMainSegment();
finishPDF(sFilepath);
return new File(sFilepath);
}
private void startPDF() throws DocumentException, FileNotFoundException {
Document d = new Document(PAGE_SIZE);
PdfWriter w = PdfWriter.getInstance(d, workingBuffer);
d.open();
d.add(new Paragraph(" "));
d.close();
w.close();
currPosition = 0;
currPage = 1;
formFillCount = 1;
}
protected void finishPDF(String sFilepath) throws DocumentException, IOException {
//Transfers data from buffer 1 to builder file
PdfReader r = new PdfReader(workingBuffer.toByteArray());
PdfStamper s = new PdfStamper(r, new FileOutputStream(sFilepath));
s.setFullCompression();
r.close();
s.close();
}
private void doMainSegment() throws FileNotFoundException, IOException, DocumentException {
File fTemplate1 = new File(TEMPLATE1_FILEPATH);
for (int i = 0; i < templateTotal; i++) {
doTemplate(fTemplate1);
}
}
private void doTemplate(File f) throws FileNotFoundException, IOException, DocumentException {
PdfReader reader = new PdfReader(new FileInputStream(f));
//Transfers data from the template input file to temporary buffer
PdfStamper stamper = new PdfStamper(reader, templateBuffer);
stamper.setFormFlattening(true);
AcroFields form = stamper.getAcroFields();
//Get size of template file via looking for "end" Acrofield
float[] area = form.getFieldPositions("end");
float size = TEMPLATE_SIZE.getHeight() - MARGIN_TOP - area[4];
//Requires Page Break
if (size >= PAGE_SIZE.getHeight() - MARGIN_TOP - MARGIN_BOTTOM + currPosition) {
PdfReader subreader = new PdfReader(workingBuffer.toByteArray());
PdfStamper substamper = new PdfStamper(subreader, storageBuffer);
currPosition = 0;
currPage++;
substamper.insertPage(currPage, PAGE_SIZE);
substamper.close();
subreader.close();
workingBuffer = storageBuffer;
storageBuffer = new ByteArrayOutputStream();
}
//Set Fields
form.setField("field1", String.format("Form Text %d", formFillCount));
form.setField("page", String.format("Page %d", currPage));
formFillCount++;
stamper.close();
reader.close();
//Read from working buffer, stamp to storage buffer, stamp template from template buffer
reader = new PdfReader(workingBuffer.toByteArray());
stamper = new PdfStamper(reader, storageBuffer);
reader.close();
reader = new PdfReader(templateBuffer.toByteArray());
PdfImportedPage page = stamper.getImportedPage(reader, 1);
PdfContentByte cb = stamper.getOverContent(currPage);
cb.addTemplate(page, 0, currPosition);
stamper.close();
reader.close();
//Reset buffers - working buffer takes on storage buffer data, storage and template buffers clear
workingBuffer = storageBuffer;
storageBuffer = new ByteArrayOutputStream();
templateBuffer = new ByteArrayOutputStream();
currPosition -= size;
}
以 DEFAULT_NUMBER_OF_TIMES 为 23 运行此程序会产生 this document 并在发送到打印机时导致失败。将其更改为 22 次 会产生 this similar-looking document(只是少了一个“行”),这没有问题并且打印成功。使用不同的 PDF 文件作为模板组件会完全改变这些数字或使其根本不会发生。
虽然这个问题可能过于具体,并且有太多因素无法合理预期其他人会重现,但可能性问题仍然存在。 文件生成会导致这种异常行为吗?什么可能导致一个文件被特定打印机接受,而另一个以相同的方式生成,只是以看似不平凡的方式不同,却被接受不能接受? iText 中是否存在因过度使用压模模板命令而产生的错误?一段时间以来,这一直是我们的一个长期存在的错误,因此非常感谢您的帮助;此外,我愿意在必要时回答问题或在聊天中进行扩展对话,以深入了解此事。
最佳答案
您的应用程序的设计或多或少滥用了原本非常好的 PdfStamper
功能。
请允许我解释一下。
页面的内容可以表示为流对象或流对象数组。使用 PdfStamper
更改页面时,此页面的内容始终是一个流对象数组,由原始流对象或添加了额外元素的原始流对象数组组成。
通过添加相同的模板,一遍又一遍地创建一个 PdfStamper
对象,您可以显着增加页面内容数组中的元素数量。您还引入了大量用于保存和恢复堆栈的 q
和 Q
运算符。您具有随机行为 的原因很清楚:可用于处理 PDF 的内存和 CPU 可能因时刻而异。上一次会有足够的资源来处理20个q
算子(保存状态),下一次就只有足够的资源来处理19个了。问题出现在进程用完资源。
虽然根据 ISO-32000-1,您创建的 PDF 并非非法,但某些 PDF 处理器只会在处理这些 PDF 时出现问题。 iText 是一个工具箱,它允许您创建 PDF,当我仔细查看时,它会让我非常高兴,但如果您不明智地使用该工具箱,它也可以让您创建可怕的 PDF。后者就是您的情况。
你应该解决这个问题,重新使用 PdfStamper
实例,而不是一遍又一遍地创建一个新的 PdfStamper
。如果那不可能,请发布另一个问题,使用更少的文字,准确解释您想要实现的目标。
假设您有许多不同的源文件,其中包含需要添加到单个页面的 PDF 片段。例如:假设每个 PDF 片段都是一张优惠券,您需要创建一个包含 30 张优惠券的工作表。比起使用单个 PdfWriter
实例,使用 getImportedPage()
导入页面并使用 addTemplate()
将它们添加到正确的位置。
当然:我不知道你的项目是关于什么的。页面优惠券的想法受到您的测试 PDF 的启发。
关于java - "Random"生成文档打印失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23657748/
有没有更好的方法用 PHP 将数据输出到 html 页面? 如果我想在 php 中用一些 var 制作一个 div,我会写类似的东西 print (''.$var.''); 或 echo "''.$v
我可以使用 java awt print 来打印文档/文件而不是使用 javax print 吗?我发现在 java awt print 中有一个选项可以使用 AttributedString 将内容
目前我通过以下方式运行 R 脚本: R --slave argument1 argument2 ... 我想知道 R 中关于如何退出脚本并发出警告的最佳实践,q() 会这样做吗? if(!file.
谁能告诉我如何编写一个程序,用 gcc 编译时打印 c ,用 g++ 编译时打印 c++? 最佳答案 #ifdef __cplusplus printf("c++\n"); #else
我需要支持在 KitKat 设备上打印,但我的目标 SDK 是 13(无法更改)。 特别是我需要打印一个 webview。 这是用于打印 webview 的 API: http://developer
我正在尝试创建一个简单的函数,其中 python 将根据您的年份输入计算年龄。我已经尝试了几种方法,但我没有运气 atm。 附:对不起,我是新手。 ame = input(" Enter your n
JavaFX 2.0 是否支持打印?我有一个文本区域,我从中获取文本然后我想打印它,但似乎没有这个功能。 当然,这里我说的是打印到打印机。 :) 最佳答案 尚不支持。作为一种解决方法,您可以使用 Ja
我试图找出printOn的重点。我查看了一些实现它的类,看起来它只是帮助打印不同数据类型的单位。这是准确的吗? 如果是这样,有人能指出我如何为我自己的类(class)实现这一点的正确方向吗?我将在可能
我无法让 IE 打印我的 Canvas (使用 excanvas 生成)...我使用的是最新版本的 excanvas。 http://dl.dropbox.com/u/997831/canvas.ht
我搜索了很多但没有人回答我的问题,我读到在这样的信号处理程序中使用 cout 是不安全的: void ctrlZHandler(int sig_num) { //SIGTSTP-18
我有兴趣打印一系列查询。我有以下代码。 start = datetime.datetime(2012, 2, 2, 6, 35, 6, 764) end = datetime.datetime(201
public class javaClass { public static void main(String [] arg) { String row1 = "A____A"
我需要写入前一行的命令,例如不带\n 的 print()。 下面是一些示例代码: a=0 print("Random string value") if a==0: print_to_prev
我有一个使用 UIKit 和 Objective C 的旧 iOS 应用程序,我目前正在将其移植到 SwiftUI 和 Swift。一切都很顺利,我喜欢 Swift 和 SwiftUI。该应用程序已经
我创建了一个求和函数,它接受一个开始编号和一个结束编号,并返回这两点之间的总和答案 def print_sum_equations(start_number,end_number):
在 Perl 6 中,print 和有什么区别? , put和 say ? 我怎么看 print 5不同,但 put 5和 say 5看起来一样。 最佳答案 put $a就像 print $a.Str
我正在使用 here 中的 getOrgChart 库,我正在尝试打印整个图表,而不仅仅是可见部分。不幸的是,当使用标准库打印功能时,它只会打印出第一部分,而我不知道如何打印整个图表(该图表相当宽,大
我制作了一个非常适合 A4 页面的 View 。现在我想打印它。请注意,我没有使用drawRect或类似的东西,只是一个带有 subview 和文本标签的普通 View 。我的问题是,我对该 View
由于 Cocoa-Java 已弃用,我正在将 Cocoa-Java 代码迁移到 Cocoa + JNI。该代码打印存储在文件中的图像。新的 Cocoa 代码基本上是: NSImage *image =
这个问题已经有答案了: Printing a TDBGrid (4 个回答) 已关闭 6 年前。 如何在不安装或下载组件的情况下打印 DBGrid? 或者 如何将 DBGrid 的数据放入 RichE
我是一名优秀的程序员,十分优秀!