Java iText填写表格/将页面复制到新文档
我正在使用Java iText填写表格/将页面复制到新文档,java,pdf,itext7,Java,Pdf,Itext7,我正在使用iText填充一个包含AcroForm的PDF模板。 现在,我想用这个模板创建一个新的PDF页面。 我的想法是填充模板PDF,用写入的字段复制页面,并将其添加到新文件中。他们的主要问题是,我们的客户希望自己设计模板。所以我不确定我是否尝试了正确的方法来解决这个问题 因此,我创建了这段代码,但现在无法工作。我得到了错误com.itextpdf.io.IOException:PDF头未找到。 我的代码 x = 1; try (PdfDocument finalDoc = new PdfD
iText
填充一个包含AcroForm
的PDF模板。
现在,我想用这个模板创建一个新的PDF页面。
我的想法是填充模板PDF,用写入的字段复制页面,并将其添加到新文件中。他们的主要问题是,我们的客户希望自己设计模板。所以我不确定我是否尝试了正确的方法来解决这个问题
因此,我创建了这段代码,但现在无法工作。我得到了错误com.itextpdf.io.IOException:PDF头未找到。
我的代码
x = 1;
try (PdfDocument finalDoc = new PdfDocument(new PdfWriter("C:\\Users\\...Final.pdf"))) {
for (HashMap<String, String> map : testValues) {
String path1 = "C:\\Users\\.....Temp.pdf"
InputStream template = templateValues.get("Template");
PdfWriter writer = new PdfWriter(path1);
try (PdfDocument pdfDoc = new PdfDocument(new PdfReader(template), writer)) {
PdfAcroForm form = PdfAcroForm.getAcroForm(pdfDoc, true);
for (HashMap.Entry<String, String> map2 : map.entrySet()) {
if (form.getField(map2.getKey()) != null) {
Map<String, PdfFormField> fields = form.getFormFields();
fields.get(map2.getKey()).setValue(map2.getValue());
}
}
} catch (IOException | PdfException ex) {
System.err.println("Ex2: " + ex.getMessage());
}
if (x != 0 && (x % 5) == 0) {
try (PdfDocument tempDoc = new PdfDocument(new PdfReader(path1))) {
PdfPage page = tempDoc.getFirstPage();
finalDoc.addPage(page.copyTo(finalDoc));
} catch (IOException | PdfException ex) {
System.err.println("Ex3: " + ex.getMessage());
}
}
x++;
}
} catch (IOException | PdfException ex) {
System.err.println("Ex: " + ex.getMessage());
}
x=1;
try(PdfDocument finalDoc=新的PdfDocument(新的PdfWriter(“C:\\Users\\\…Final.pdf”)){
for(HashMap映射:testValues){
String path1=“C:\\Users\\..…Temp.pdf”
InputStream template=templateValues.get(“模板”);
PdfWriter writer=新的PdfWriter(路径1);
try(PdfDocument pdfDoc=newpdfdocument(newpdfreader(模板)、writer)){
PdfAcroForm form=PdfAcroForm.getAcroForm(pdfDoc,true);
对于(HashMap.Entry map2:map.entrySet()){
if(form.getField(map2.getKey())!=null){
映射字段=form.getFormFields();
fields.get(map2.getKey()).setValue(map2.getValue());
}
}
}捕获(IOException | PDFEException ex){
System.err.println(“Ex2:+ex.getMessage());
}
如果(x!=0&(x%5)==0){
try(PdfDocument tempDoc=newpdfdocument(newpdfreader(path1))){
PdfPage page=tempDoc.getFirstPage();
finalDoc.addPage(page.copyTo(finalDoc));
}捕获(IOException | PDFEException ex){
System.err.println(“Ex3:+ex.getMessage());
}
}
x++;
}
}捕获(IOException | PDFEException ex){
System.err.println(“Ex:+Ex.getMessage());
}
完成向PDF文档添加内容后关闭它们。完成向PDF文档添加内容后关闭它们。第1部分-PDF标题缺失
这似乎是由于您试图在已读取的循环中重新读取InputStream/而导致的(并且,根据PdfReader的配置,该循环已关闭)。解决这一问题取决于所使用的InputStream的具体类型-如果您想将其保留为简单的InputStream(与更具体但更具能力的InputStream类型相比),则需要首先将字节从流中提取到内存中(例如ByteArrayOutputStream),然后基于这些字节创建PDF阅读器
i、 e
第2部分-其他问题
两件事
File acroFormTemplate=新文件(“someTemplate.pdf”);
Map someMapOfFieldToValues=新HashMap();
试一试(
PdfDocument finalOutput=新的PdfDocument(新的PdfWriter(新的FileOutputStream)(新文件(“finalOutput.pdf”));
) {
对于(/*某些循环条件*/int x=0;x<5;x++){
//对于循环的每个迭代,在内存中创建一个临时
//PDF来处理表单字段编辑。
ByteArrayOutputStream tmp=新的ByteArrayOutputStream();
试一试(
PdfDocument filledAcroFormTemplate=新PdfDocument(新PDF阅读器(新文件输入流(acroFormTemplate)),新PDF编写器(tmp));
) {
PdfAcroForm acroForm=PdfAcroForm.getAcroForm(filledInAcroFormTemplate,true);
对于(PdfFormField字段:acroForm.getFormFields().values()){
if(someMapOfFieldToValues.containsKey(field.getFieldName())){
setValue(someMapOfFieldToValues.get(field.getFieldName());
}
}
//请注意,因为我们多次添加模板
//我们需要采取字段重命名策略,以确保字段
//最终文件中的唯一性。为了演示起见
//我们只需将它们重命名为前缀w/我们的循环计数器
List fieldNames=new ArrayList();
fieldNames.addAll(acroForm.getFormFields().keySet());//避免混淆修改
for(字符串字段名:字段名){
acroForm.renameField(字段名,x+“”+字段名);
}
}
//对于所有PDF定稿,临时PDF需要“关闭”
//神奇的事情发生了…所以打开新的只读版本作为
//来自内存中bucket-o-bytes的合并源
试一试(
PdfDocument readOnlyFilledInAcroFormTemplate=新的PdfDocument(新的PdfReader(新的ByteArrayInputStream(tmp.toByteArray()));
) {
//虽然PdfPage.copyTo可能适用于简单页面,但PdfDocument.copyPagesTo
//是更全面的副本(更广泛地支持复制大纲和标记内容)
ByteArrayOutputStream templateBuffer = new ByteArrayOutputStream();
while ((int c = template.read()) > 0) templateBuffer.write(c);
for (/* your loop */) {
...
PdfDocument filledInAcroFormTemplate = new PdfDocument(new PdfReader(new ByteArrayInputStream(templateBuffer.toByteArray())), new PdfWriter(tmp))
...
File acroFormTemplate = new File("someTemplate.pdf");
Map<String, String> someMapOfFieldToValues = new HashMap<>();
try (
PdfDocument finalOutput = new PdfDocument(new PdfWriter(new FileOutputStream(new File("finalOutput.pdf")));
) {
for (/* some looping condition */int x = 0; x < 5; x++) {
// for each iteration of the loop, create a temporary in-memory
// PDF to handle form field edits.
ByteArrayOutputStream tmp = new ByteArrayOutputStream();
try (
PdfDocument filledInAcroFormTemplate = new PdfDocument(new PdfReader(new FileInputStream(acroFormTemplate)), new PdfWriter(tmp));
) {
PdfAcroForm acroForm = PdfAcroForm.getAcroForm(filledInAcroFormTemplate, true);
for (PdfFormField field : acroForm.getFormFields().values()) {
if (someMapOfFieldToValues.containsKey(field.getFieldName())) {
field.setValue(someMapOfFieldToValues.get(field.getFieldName()));
}
}
// NOTE that because we're adding the template multiple times
// we need to adopt a field renaming strategy to ensure field
// uniqueness in the final document. For demonstration's sake
// we'll just rename them prefixed w/ our loop counter
List<String> fieldNames = new ArrayList<>();
fieldNames.addAll(acroForm.getFormFields().keySet()); // avoid ConfurrentModification
for (String fieldName : fieldNames) {
acroForm.renameField(fieldName, x+"_"+fieldName);
}
}
// the temp PDF needs to be "closed" for all the PDF finalization
// magic to happen...so open up new read-only version to act as
// the source for the merging from our in-memory bucket-o-bytes
try (
PdfDocument readOnlyFilledInAcroFormTemplate = new PdfDocument(new PdfReader(new ByteArrayInputStream(tmp.toByteArray())));
) {
// although PdfPage.copyTo will probably work for simple pages, PdfDocument.copyPagesTo
// is a more comprehensive copy (wider support for copying Outlines and Tagged content)
// so it's more suitable for general page-copy use. Also, since we're copying AcroForm
// content, we need to use the PdfPageFormCopier
readOnlyFilledInAcroFormTemplate.copyPagesTo(1, 1, finalOutput, new PdfPageFormCopier());
}
}
}