连接pdf而不展平,但保留字段

连接pdf而不展平,但保留字段,pdf,itext,flatten,Pdf,Itext,Flatten,我试图填写一个pdf模板,并在最后添加另一个pdf。 我可以将页面添加到另一个pdf,但问题是,当我这样做时,即使我不使用stamper.setFormFlating(true),我的字段也会丢失 这是我的代码: import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.text.ParseE

我试图填写一个pdf模板,并在最后添加另一个pdf。 我可以将页面添加到另一个pdf,但问题是,当我这样做时,即使我不使用stamper.setFormFlating(true),我的字段也会丢失

这是我的代码:

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.io.FileUtils;

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.AcroFields;
import com.itextpdf.text.pdf.PdfCopy;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfSmartCopy;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.PdfWriter;

public class ForStack {

    public static void main(String[] args) throws IOException, DocumentException, ParseException {
        createContractWithMoreFile();
    }

    public static void createContractWithMoreFile()
            throws IOException, DocumentException, ParseException {

        String linkPDF = "resources/pdfs/User.pdf";

        PdfReader reader = new PdfReader(linkPDF);
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        PdfStamper stamper = new PdfStamper(reader, baos);

        PdfWriter writer = stamper.getWriter();
        writer.setPdfVersion(PdfWriter.VERSION_1_7);
        AcroFields form = stamper.getAcroFields();

        form.setField("Name", "Jhon");
        stamper.close();
        String out = "results/merged.pdf";

        List<byte[]> listOfPdfFiles = new ArrayList<>();
        listOfPdfFiles.add(baos.toByteArray());

        byte[] informativaPrivacy = getPdfByteArray("resources/pdfs/second.pdf");
        listOfPdfFiles.add(informativaPrivacy);

        concatenatePdfs(listOfPdfFiles, new File(out));

        baos.close();
        reader.close();

    }

    public static byte[] getPdfByteArray(String filePath) {
        File fileP = new File(filePath);
        byte[] result;
        try {
            result = FileUtils.readFileToByteArray(fileP);
            return result;
        } catch (IOException e) {
            return null;
        }
    }

    public static void concatenatePdfs(List<byte[]> listOfPdfFiles, File outputFile) throws DocumentException, IOException {
        Document document = new Document();
        FileOutputStream outputStream = new FileOutputStream(outputFile);
        PdfCopy copy = new PdfSmartCopy(document, outputStream);
        document.open();
        for (byte[] inFile : listOfPdfFiles) {
            PdfReader reader = new PdfReader(inFile);
            copy.addDocument(reader);
            reader.close();
        }
        document.close();
    }
}
import java.io.ByteArrayOutputStream;
导入java.io.File;
导入java.io.FileOutputStream;
导入java.io.IOException;
导入java.text.ParseException;
导入java.util.ArrayList;
导入java.util.List;
导入org.apache.commons.io.FileUtils;
导入com.itextpdf.text.Document;
导入com.itextpdf.text.DocumentException;
导入com.itextpdf.text.pdf.AcroFields;
导入com.itextpdf.text.pdf.PdfCopy;
导入com.itextpdf.text.pdf.PdfReader;
导入com.itextpdf.text.pdf.PdfSmartCopy;
导入com.itextpdf.text.pdf.PdfStamper;
导入com.itextpdf.text.pdf.PdfWriter;
公开课预赛{
公共静态void main(字符串[]args)引发IOException、DocumentException、ParseException{
createContractWithMoreFile();
}
public static void createContractWithMoreFile()
抛出IOException、DocumentException、ParseException{
String linkPDF=“resources/pdfs/User.pdf”;
PdfReader reader=新PdfReader(linkPDF);
ByteArrayOutputStream bas=新的ByteArrayOutputStream();
PdfStamper压模=新PdfStamper(读卡器,BAS);
PdfWriter writer=stamper.getWriter();
writer.setPdfVersion(PdfWriter.VERSION_1_7);
AcroFields form=stamp.getAcroFields();
设置域(“名称”、“Jhon”);
压模关闭();
String out=“results/merged.pdf”;
List-listopfdffiles=new-ArrayList();
添加(baos.toByteArray());
byte[]informativaPrivacy=getPdfByteArray(“resources/pdfs/second.pdf”);
添加(informativaPrivacy);
连接EPDF(列表OFPDF文件,新文件(输出));
baos.close();
reader.close();
}
公共静态字节[]getPdfByteArray(字符串文件路径){
File fileP=新文件(filePath);
字节[]结果;
试一试{
结果=FileUtils.readFileToByteArray(fileP);
返回结果;
}捕获(IOE异常){
返回null;
}
}
公共静态void concatenatePdfs(List ListOfDfFiles,File outputFile)引发DocumentException,IOException{
文档=新文档();
FileOutputStream outputStream=新的FileOutputStream(outputFile);
PdfCopy copy=新的PdfSmartCopy(文档、输出流);
document.open();
for(字节[]填充:ListOffDFFiles){
PdfReader读取器=新PdfReader(填充);
副本。添加文件(读卡器);
reader.close();
}
document.close();
}
}
这是我正在使用的文件

  • 输出文件不是我想要的:

    那么为什么输出pdf会丢失我的字段呢?没有连接,就没有平坦化

    正如您在我的结果文件中看到的,没有字段,因此如果您不想再次看到它,我必须使用adobe Acrobat,使用->查看(Vista)->工具(Importazioni)->创建表单(Prepara Modulo)。 但如果我这样做并试图退出pdf,Adobe会要求我保存它更改的pdf,这不是我想要的

    我想要的输出pdf在这里: 使用结果文件中丢失的字段
    您的代码中有许多错误。例如:您不需要
    org.w3c.dom.Document
    ,您需要
    com.itextpdf.text.Document
    ;此错误导致您的代码甚至无法编译

    我修复了错误,最终得到了这个SSCCE:

    package sandbox.merge;
    
    import java.io.ByteArrayOutputStream;
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.text.ParseException;
    import java.util.ArrayList;
    import java.util.List;
    
    import org.apache.commons.io.FileUtils;
    
    import com.itextpdf.text.Document;
    import com.itextpdf.text.DocumentException;
    import com.itextpdf.text.pdf.AcroFields;
    import com.itextpdf.text.pdf.PdfCopy;
    import com.itextpdf.text.pdf.PdfReader;
    import com.itextpdf.text.pdf.PdfSmartCopy;
    import com.itextpdf.text.pdf.PdfStamper;
    import com.itextpdf.text.pdf.PdfWriter;
    
    public class ForStack {
    
        public static void main(String[] args) throws IOException, DocumentException, ParseException {
            createContractWithMoreFile();
        }
    
        public static void createContractWithMoreFile()
                throws IOException, DocumentException, ParseException {
    
            String linkPDF = "resources/pdfs/User.pdf";
    
            PdfReader reader = new PdfReader(linkPDF);
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            PdfStamper stamper = new PdfStamper(reader, baos);
    
            PdfWriter writer = stamper.getWriter();
            writer.setPdfVersion(PdfWriter.VERSION_1_7);
            AcroFields form = stamper.getAcroFields();
    
            form.setField("Name", "Jhon");
            stamper.setFormFlattening(true);
            stamper.close();
            String out = "results/merged.pdf";
    
            List<byte[]> listOfPdfFiles = new ArrayList<>();
            listOfPdfFiles.add(baos.toByteArray());
    
            byte[] informativaPrivacy = getPdfByteArray("resources/pdfs/second.pdf");
            listOfPdfFiles.add(informativaPrivacy);
    
            concatenatePdfs(listOfPdfFiles, new File(out));
    
            baos.close();
            reader.close();
    
        }
    
        public static byte[] getPdfByteArray(String filePath) {
            File fileP = new File(filePath);
            byte[] result;
            try {
                result = FileUtils.readFileToByteArray(fileP);
                return result;
            } catch (IOException e) {
                return null;
            }
        }
    
        public static void concatenatePdfs(List<byte[]> listOfPdfFiles, File outputFile) throws DocumentException, IOException {
            Document document = new Document();
            FileOutputStream outputStream = new FileOutputStream(outputFile);
            PdfCopy copy = new PdfSmartCopy(document, outputStream);
            document.open();
            for (byte[] inFile : listOfPdfFiles) {
                PdfReader reader = new PdfReader(inFile);
                copy.addDocument(reader);
                reader.close();
            }
            document.close();
        }
    }
    
    代码中缺少该行,这解释了为什么表单没有展平

    总结:

    当您展平表单时,您有:

    这里曾经是字段
    “Name”
    ,我们看到了值
    “Jhon”
    ,但字段本身消失了:这就是展开的意义:删除所有交互

    如果不展平表单,则会出现以下情况:

    互动领域仍然存在,没有平台。它是用值
    “Jhon”
    填写的

    OP似乎希望像第一个屏幕截图中那样展平表单,同时保持第二个屏幕截图中的字段。这是一种反驳。如果需要答案,OP应澄清预期结果

    iText版本


    顺便说一下:我用iText 5.5.13来测试这个。请注意,iText 5不再受支持,除非您是付费客户。当前版本为iText 7.1.2,但在7.1.2中,
    PdfStamper
    类不再存在。在iText 7中,填写表单和合并文档的方式有所不同。

    Bruno的回答最初假设为
    压模。来自OP原始代码的setFormFlatting(true)
    调用表明表单应该被压平。事实证明,情况并非如此,这些字段本应保留下来

    因此,Bruno删除了表单展平线,并指出结果现在是可编辑的,即表单字段存在。但是OP仍然坚持说他们已经走了

    事实证明,两人都是对的,每个人都有自己的方式。区别在于:表单字段作为页面上的小部件注释出现在输出中,但是AcroForm表单定义消失了

    要使iText 5.5.x
    PdfCopy
    实例在包含所有复制源文档的合并表单字段的目标文档中创建一个AcroForm表单定义,必须激活其合并字段模式

    如果您想知道为什么此模式在默认情况下不处于活动状态:它有一个缺点,所有源
    PdfReader
    对象必须保持打开状态,直到目标
    PdfCopy
    实例关闭,这可能会导致子对象
    stamper.setFormFlattening(true);