简体   繁体   中英

iText PdfCopy creates editable pdf document

I have a template pdf file which is used in a spring boot application. I need to update values in this template based on user input per request. Also in the request i will get multiple pdf files I need to merge those files along with updated file which is first page of final pdf.

I am using iText with Spring Boot. I am able to update the values in template and merge file content as well but final pdf is coming as editable with files are hidden. If i click on that filed i can able to see my values also can able to edit.

public void mergefiles(Map<String, String> tempData,MultipartFile[] userInfoFiles) 
            throws Exception{



        FileOutputStream mergeOutStream = new FileOutputStream(new File("C:\\UpdateFile\\mergepath\\updatetem.pdf")); //To update user content to Template

        PdfReader reader = new PdfReader(new FileInputStream(new File("C:\\UpdateFile\\template\\template.pdf"))); //Template File Stream
        PdfStamper stamper = new PdfStamper(reader, mergeOutStream);

        stamper.setFormFlattening(false);
        AcroFields form = stamper.getAcroFields();

        Map<String, Item> fieldMap = form.getFields();


        for (String key : fieldMap.keySet()) {
            String fieldValue = dataMap.get(key);
            if (fieldValue != null) {

                form.setField(key, fieldValue);
            }
        }
        //Above part creates updated pdf with read only

        //Below section creates merged file but first page is editable with 
        //filed values are hidden.

        Document mergePdfDoc = new Document();
        PdfCopy pdfCopy;
        boolean smartCopy = false;

        FileOutputStream newmergeOutStream = new FileOutputStream(new File("C:\\UpdateFile\\mergepath\\newmerged.pdf"));

        if(smartCopy)
            pdfCopy = new PdfSmartCopy(mergePdfDoc, newmergeOutStream);
        else
            pdfCopy = new PdfCopy(mergePdfDoc, newmergeOutStream);



        mergePdfDoc.open();

        pdfCopy.addDocument(stamper.getReader());
        pdfCopy.freeReader(stamper.getReader());


        PdfReader[] pdfReader = new PdfReader[userInfoFiles.length];



        for(int i=0; i<=userInfoFiles.length-1;i++) {
                pdfReader[i] = new PdfReader(userInfoFiles[i].getInputStream());
                pdfCopy.addDocument(pdfReader[i]);
                pdfCopy.freeReader(pdfReader[i]);
                pdfReader[i].close();
        }
        stamper.close();
        mergeOutStream.close();
        mergePdfDoc.close();
    }

Any input why final pdf is in editable form and filed values are hidden. I have to create a merged document and get ByteArray stream of the final document as its input to another function call.I am Using iText5.

The problem is that you add the PdfReader the PdfStamper is based on as input to your PdfCopy :

pdfCopy.addDocument(stamper.getReader());

The reader a stamper works on is dirty: some changes applied via the stamper are made to the objects the reader holds, some are only in the stamper or its output.

Eg in your case the form fields are already defined in the original pdf. The field value is added to this field directly. Thus, it gets changed in the reader. But the appearance, the field visualization including a drawing of its current value, gets generated in a new indirect object which is added to the stamper output. Thus, there still is the original, empty visualization in the reader.

In a pdf viewer, therefore, the PdfCopy result at first has the looks of empty fields (as the appearances have been generated in the stamper only) but when editing a field, the changed value becomes visible (because the field editor is initialized with the field value).

To fix this, don't use the dirty reader but instead create a new, clean reader from the stamping result.

First create the stamped file:

    FileOutputStream mergeOutStream = new FileOutputStream(new File("C:\\UpdateFile\\mergepath\\updatetem.pdf")); //To update user content to Template

    PdfReader reader = new PdfReader(new FileInputStream(new File("C:\\UpdateFile\\template\\template.pdf"))); //Template File Stream
    PdfStamper stamper = new PdfStamper(reader, mergeOutStream);

    stamper.setFormFlattening(false);
    AcroFields form = stamper.getAcroFields();

    Map<String, Item> fieldMap = form.getFields();

    for (String key : fieldMap.keySet()) {
        String fieldValue = dataMap.get(key);
        if (fieldValue != null) {
            form.setField(key, fieldValue);
        }
    }
    stamper.close();

And then merge:

    Document mergePdfDoc = new Document();
    PdfCopy pdfCopy;
    boolean smartCopy = false;

    FileOutputStream newmergeOutStream = new FileOutputStream(new File("C:\\UpdateFile\\mergepath\\newmerged.pdf"));

    if(smartCopy)
        pdfCopy = new PdfSmartCopy(mergePdfDoc, newmergeOutStream);
    else
        pdfCopy = new PdfCopy(mergePdfDoc, newmergeOutStream);

    mergePdfDoc.open();

    PdfReader reader = new PdfReader(new FileInputStream(new File("C:\\UpdateFile\\mergepath\\updatetem.pdf")));
    pdfCopy.addDocument(reader);
    pdfCopy.freeReader(reader);

    PdfReader[] pdfReader = new PdfReader[userInfoFiles.length];

    for(int i=0; i<=userInfoFiles.length-1;i++) {
            pdfReader[i] = new PdfReader(userInfoFiles[i].getInputStream());
            pdfCopy.addDocument(pdfReader[i]);
            pdfCopy.freeReader(pdfReader[i]);
            pdfReader[i].close();
    }

    mergeOutStream.close();
    mergePdfDoc.close();
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM