合并加密的PDF文件程序化异常

huangapple go评论67阅读模式
英文:

Merge encrypted pdf file programmatically exception

问题

public void mergeMyFiles(String filesToBeMerged[], String mergedFileLocation, String password) {
    try {
        int pageOffset = 0;
        ArrayList masterBookMarkList = new ArrayList();

        int fileIndex = 0;
        String outFile = mergedFileLocation;
        Document document = null;
        PdfCopy writer = null;
        PdfReader reader = null;
        PdfReader.unethicalreading = true;
        for (fileIndex = 0; fileIndex < filesToBeMerged.length; fileIndex++) {
            reader = new PdfReader(filesToBeMerged[fileIndex], password.getBytes());
            reader.consolidateNamedDestinations();
            int totalPages = reader.getNumberOfPages();
            List bookmarks = SimpleBookmark.getBookmark(reader);
            if (bookmarks != null) {
                if (pageOffset != 0)
                    SimpleBookmark.shiftPageNumbers(bookmarks, pageOffset, null);
                masterBookMarkList.addAll(bookmarks);
                System.out.println("Bookmarks found and storing...");
            } else {
                System.out.println("No bookmarks in this file...");
            }
            pageOffset += totalPages;

            if (fileIndex == 0) {
                document = new Document(reader.getPageSizeWithRotation(1));
                writer = new PdfCopy(document, new FileOutputStream(outFile));
                document.open();
            }
            PdfImportedPage page;
            for (int currentPage = 1; currentPage <= totalPages; currentPage++) {
                page = writer.getImportedPage(reader, currentPage);
                writer.addPage(page);
            }

            PRAcroForm form = reader.getAcroForm();
            if (form != null) {
                writer.addDocument(reader);
                System.out.println("Acroforms found and copied");
            } else
                System.out.println("Acroforms not found for this file");

            System.out.println();
        }
        if (!masterBookMarkList.isEmpty()) {
            writer.setOutlines(masterBookMarkList);
            System.out.println("All bookmarks combined and added");
        } else {
            System.out.println("No bookmarks to add in the new file");
        }
        document.close();
    } catch (Exception e) {
        e.printStackTrace();
    }
}
public void mergePDFFiles(String FILE1, String FILE2, String mergedFileLocation, String password) {
    try {
        PdfReader pdf1 = new PdfReader(FILE1);
        pdf1.setUnethicalReading(true);
        PdfReader pdf2 = new PdfReader(FILE2);
        pdf2.setUnethicalReading(true);
        PdfDocument pdfDocument = new PdfDocument(pdf1, new PdfWriter(mergedFileLocation));
        PdfDocument pdfDocument2 = new PdfDocument(pdf2);

        PdfMerger merger = new PdfMerger(pdfDocument);
        merger.merge(pdfDocument2, 1, pdfDocument2.getNumberOfPages());

        pdfDocument2.close();
        pdfDocument.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

Please note that I have removed the logcat results and the links to the sample PDF files, as requested.

英文:

I have been using the following code to merge encrypted pdf files programmatically.

public void mergeMyFiles(String filesToBeMerged[], String mergedFileLocation, String password) {
    try {
        int pageOffset = 0;
        ArrayList masterBookMarkList = new ArrayList();

        int fileIndex = 0;
        String outFile = mergedFileLocation;
        Document document = null;
        PdfCopy writer = null;
        PdfReader reader = null;
        PdfReader.unethicalreading = true;
        for (fileIndex = 0; fileIndex &lt; filesToBeMerged.length; fileIndex++) {
            /**
             * Create a reader for the file that we are reading
             */
            reader = new PdfReader(filesToBeMerged[fileIndex], password.getBytes());
            /**
             * Replace all the local named links with the actual destinations.
             */
            reader.consolidateNamedDestinations();

            /**
             * Retrieve the total number of pages for this document
             */
            int totalPages = reader.getNumberOfPages();

            /**
             * Get the list of bookmarks for the current document
             * If the bookmarks are not empty, store the bookmarks
             * into a master list
             */
            List bookmarks = SimpleBookmark.getBookmark(reader);
            if (bookmarks != null) {
                if (pageOffset != 0)
                    SimpleBookmark.shiftPageNumbers(bookmarks, pageOffset,
                        null);
                masterBookMarkList.addAll(bookmarks);
                System.out.println(&quot;Bookmarks found and storing...&quot;);
            } else {
                System.out.println(&quot;No bookmarks in this file...&quot;);
            }
            pageOffset += totalPages;

            /**
             * Merging the files to the first file.
             * If we are passing file1, file2 and file3,
             * we will merge file2 and file3 to file1.
             */
            if (fileIndex == 0) {
                /**
                 * Create the document object from the reader
                 */
                document = new Document(reader.getPageSizeWithRotation(1));

                /**
                 * Create a pdf write that listens to this document.
                 * Any changes to this document will be written the file
                 *
                 * outFile is a location where the final merged document
                 * will be written to.
                 */

                System.out.println(&quot;Creating an empty PDF...&quot;);
                writer = new PdfCopy(document, new FileOutputStream(outFile));
                /**
                 * Open this document
                 */
                document.open();
            }
            /**
             * Add the conent of the file into this document (writer).
             * Loop through multiple Pages
             */
            System.out.println(&quot;Merging File: &quot; + filesToBeMerged[fileIndex]);
            PdfImportedPage page;
            for (int currentPage = 1; currentPage &lt;= totalPages; currentPage++) {
                page = writer.getImportedPage(reader, currentPage);
                writer.addPage(page);
            }

            /**
             * This will get the documents acroform.
             * This will return null if no acroform is part of the document.
             *
             * Acroforms are PDFs that have been turned into fillable forms.
             */
            System.out.println(&quot;Checking for Acroforms&quot;);
            PRAcroForm form = reader.getAcroForm();
            if (form != null) {
                //writer.copyAcroForm(reader);
                writer.addDocument(reader);
                System.out.println(&quot;Acroforms found and copied&quot;);
            } else
                System.out.println(&quot;Acroforms not found for this file&quot;);

            System.out.println();
        }
        /**
         * After looping through all the files, add the master bookmarklist.
         * If individual PDF documents had separate bookmarks, master bookmark
         * list will contain a combination of all those bookmarks in the
         * merged document.
         */
        if (!masterBookMarkList.isEmpty()) {
            writer.setOutlines(masterBookMarkList);
            System.out.println(&quot;All bookmarks combined and added&quot;);

        } else {
            System.out.println(&quot;No bookmarks to add in the new file&quot;);

        }

        /**
         * Finally Close the main document, which will trigger the pdfcopy
         * to write back to the filesystem.
         */
        document.close();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

I started getting this error recently upon trying to create the pdfReader at this line of code:

reader = new PdfReader(filesToBeMerged[fileIndex], password.getBytes());

> com.itextpdf.text.exceptions.InvalidPdfException: Unknown encryption type R = 6
at com.itextpdf.text.pdf.PdfReader.readPdf(PdfReader.java:738)
at com.itextpdf.text.pdf.PdfReader.<init>(PdfReader.java:181)
at com.itextpdf.text.pdf.PdfReader.<init>(PdfReader.java:219)
at com.itextpdf.text.pdf.PdfReader.<init>(PdfReader.java:207)
at com.project.mainPageShop.mergeMyFiles(mainPageShop.java:4368)
at com.project.mainPageShop$DownloadFileAsync.onPostExecute(mainPageShop.java:11757)
at com.project.mainPageShop$DownloadFileAsync.onPostExecute(mainPageShop.java:11628)
at android.os.AsyncTask.finish(AsyncTask.java:755)
at android.os.AsyncTask.access$900(AsyncTask.java:192)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:772)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:237)
at android.app.ActivityThread.main(ActivityThread.java:7814)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1068)

Kindly note that the password is correct, and same file which use to work using this code, is now raising this exception.

UPDATE:

I have used the following code using com.itextpdf:itext7-core:7.0.2

public void mergePDFFiles(String FILE1, String FILE2, String mergedFileLocation, String password) {
    try {
        PdfReader pdf1 = new PdfReader(FILE1);
        pdf1.setUnethicalReading(true);
        PdfReader pdf2 = new PdfReader(FILE2);
        pdf2.setUnethicalReading(true);
        PdfDocument pdfDocument = new PdfDocument(pdf1, new PdfWriter(mergedFileLocation));
        PdfDocument pdfDocument2 = new PdfDocument(pdf2);

        PdfMerger merger = new PdfMerger(pdfDocument);
        merger.merge(pdfDocument2, 1, pdfDocument2.getNumberOfPages());

        pdfDocument2.close();
        pdfDocument.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

This is the logcat Result:

>FATAL EXCEPTION: main
Process: com.project, PID: 7665
com.itextpdf.kernel.PdfException: Unknown encryption type R == 6.
at com.itextpdf.kernel.pdf.PdfEncryption.readAndSetCryptoModeForStdHandler(PdfEncryption.java:508)
at com.itextpdf.kernel.pdf.PdfEncryption.<init>(PdfEncryption.java:181)
at com.itextpdf.kernel.pdf.PdfReader.readDecryptObj(PdfReader.java:1061)
at com.itextpdf.kernel.pdf.PdfReader.readPdf(PdfReader.java:531)
at com.itextpdf.kernel.pdf.PdfDocument.open(PdfDocument.java:1585)
at com.itextpdf.kernel.pdf.PdfDocument.<init>(PdfDocument.java:281)
at com.itextpdf.kernel.pdf.PdfDocument.<init>(PdfDocument.java:249)
at com.project.mainPageShop.mergePDFFiles(mainPageShop.java:4353)
at com.neelwafurat.iKitabForAndroid.mainPageShop$DownloadFileAsync.onPostExecute(mainPageShop.java:11788)
at com.project.mainPageShop$DownloadFileAsync.onPostExecute(mainPageShop.java:11659)
at android.os.AsyncTask.finish(AsyncTask.java:755)
at android.os.AsyncTask.access$900(AsyncTask.java:192)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:772)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:237)
at android.app.ActivityThread.main(ActivityThread.java:7814)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1068)

The error is occurring at the following line:

PdfDocument pdfDocument = new PdfDocument(pdf1, new PdfWriter(mergedFileLocation));

Find below links for sample encrypted pdf files used with password: 123456

https://smallpdf.com/shared#st=8921059d-6615-4264-a3f6-c76d476dc168&amp;fn=test+1.pdf&amp;ct=1602755420749&amp;tl=share-document&amp;rf=link

https://smallpdf.com/shared#st=7d3c11c7-b34d-4399-bc03-c66b7be788d0&amp;fn=test+2.pdf&amp;ct=1602755505331&amp;tl=share-document&amp;rf=link

答案1

得分: 2

Revision 6 of the standard security handler is not supported in iText 5 or iText 7.0.2. It was introduced in iText 7.1.0 in the context of PDF 2.0 support.

I have slightly tweaked your code sample to test. Note that you were not passing the password to the PdfReader instance.

Also note that the password you shared for the sample PDFs (123456) is the user password, not the owner password.

A user password, also called open password, is used to open a PDF document, i.e. to give access to the content. All other restrictions are handled by an owner password, also called permissions password, e.g. allowing/preventing a document from being printed.

For your sample documents, both the open password and permissions password are set:

合并加密的PDF文件程序化异常

If you have the owner password available, you should use it to process the PDF, i.e. pass it to the PdfReader instance. That allows you to avoid the unethicalreading setting.

Test code:

public void mergePDFFiles(String FILE1, String FILE2, String mergedFileLocation, String password)
{
try {
PdfReader pdf1 = new PdfReader(FILE1,
new ReaderProperties().setPassword(password.getBytes()));
pdf1.setUnethicalReading(true);
PdfReader pdf2 = new PdfReader(FILE2,
new ReaderProperties().setPassword(password.getBytes()));
pdf2.setUnethicalReading(true);
PdfDocument pdfDocument = new PdfDocument(pdf1, new PdfWriter(mergedFileLocation));
PdfDocument pdfDocument2 = new PdfDocument(pdf2);
PdfMerger merger = new PdfMerger(pdfDocument);
merger.merge(pdfDocument2, 1, pdfDocument2.getNumberOfPages());
pdfDocument2.close();
pdfDocument.close();
} catch (IOException e) {
e.printStackTrace();
}
}

iText 7.0.2 does not support revision 6, as you've noticed:

Exception in thread "main" com.itextpdf.kernel.PdfException: Unknown encryption type R == 6.
at com.itextpdf.kernel.pdf.PdfEncryption.readAndSetCryptoModeForStdHandler(PdfEncryption.java:508)
at com.itextpdf.kernel.pdf.PdfEncryption.<init>(PdfEncryption.java:181)
at com.itextpdf.kernel.pdf.PdfReader.readDecryptObj(PdfReader.java:1061)
at com.itextpdf.kernel.pdf.PdfReader.readPdf(PdfReader.java:531)
at com.itextpdf.kernel.pdf.PdfDocument.open(PdfDocument.java:1585)
at com.itextpdf.kernel.pdf.PdfDocument.<init>(PdfDocument.java:281)
at com.itextpdf.kernel.pdf.PdfDocument.<init>(PdfDocument.java:249)

Starting from iText 7.1.0 up until the current release (7.1.13), your 2 sample files will merge correctly, resulting in a 4-page output file.

英文:

Revision 6 of the standard security handler is not supported in iText 5 or iText 7.0.2. It was introduced in iText 7.1.0 in the context of PDF 2.0 support.

I have slightly tweaked your code sample to test. Note that you were not passing the password to the PdfReader instance.

Also note that the password you shared for the sample PDFs (123456) is the user password, not the owner password.

A user password, also called open password, is used to open a PDF document, i.e. to give access to the content. All other restrictions are handled by an owner password, also called permissions password, e.g. allowing/preventing a document being printed.

For your sample documents, both the open password and permissions password are set:

合并加密的PDF文件程序化异常

If you have the owner password available, you should use it the process the PDF, i.e. pass it to the PdfReader instance. That allows you to avoid the unethicalreading setting.

Test code:

public void mergePDFFiles(String FILE1, String FILE2, String mergedFileLocation, String password)
{
try {
PdfReader pdf1 = new PdfReader(FILE1,
new ReaderProperties().setPassword(password.getBytes()));
pdf1.setUnethicalReading(true);
PdfReader pdf2 = new PdfReader(FILE2,
new ReaderProperties().setPassword(password.getBytes()));
pdf2.setUnethicalReading(true);
PdfDocument pdfDocument = new PdfDocument(pdf1, new PdfWriter(mergedFileLocation));
PdfDocument pdfDocument2 = new PdfDocument(pdf2);
PdfMerger merger = new PdfMerger(pdfDocument);
merger.merge(pdfDocument2, 1, pdfDocument2.getNumberOfPages());
pdfDocument2.close();
pdfDocument.close();
} catch (IOException e) {
e.printStackTrace();
}
}

iText 7.0.2 does not support revision 6, as you've noticed:

Exception in thread &quot;main&quot; com.itextpdf.kernel.PdfException: Unknown encryption type R == 6.
at com.itextpdf.kernel.pdf.PdfEncryption.readAndSetCryptoModeForStdHandler(PdfEncryption.java:508)
at com.itextpdf.kernel.pdf.PdfEncryption.&lt;init&gt;(PdfEncryption.java:181)
at com.itextpdf.kernel.pdf.PdfReader.readDecryptObj(PdfReader.java:1061)
at com.itextpdf.kernel.pdf.PdfReader.readPdf(PdfReader.java:531)
at com.itextpdf.kernel.pdf.PdfDocument.open(PdfDocument.java:1585)
at com.itextpdf.kernel.pdf.PdfDocument.&lt;init&gt;(PdfDocument.java:281)
at com.itextpdf.kernel.pdf.PdfDocument.&lt;init&gt;(PdfDocument.java:249)

Starting from iText 7.1.0 up until the current release (7.1.13), your 2 sample files will merge correctly, resulting in a 4-page output file.

huangapple
  • 本文由 发表于 2020年10月12日 20:26:59
  • 转载请务必保留本文链接:https://go.coder-hub.com/64317905.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定