首页 > 解决方案 > Itext Pdf可以提取文本但不能使用所有者密码从pdf复制页面?

问题描述

我正在使用 itext pdf 作为 java 编程语言从 pdf 文档中提取文本。通过一种PdfReaderContentParser方法,可以提取所需的文本内容。但我的PdfCopy方法导致IllegalArgumentException.

这是我的PdfReaderContentParser方法的例子:

import java.io.File;
import java.io.FileOutputStream;
import java.io.PrintWriter;

import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.parser.PdfReaderContentParser;
import com.itextpdf.text.pdf.parser.SimpleTextExtractionStrategy;
import com.itextpdf.text.pdf.parser.TextExtractionStrategy;

public class PdfExtract {

    public PdfExtract()  throws Exception{
        File f = new File( "D:/disertasi orang penting/OSD/disertasi doktor OSD.pdf" );
        PdfReader reader = new PdfReader(f.getPath()); 
        PdfReaderContentParser parser = new PdfReaderContentParser(reader);
        TextExtractionStrategy strategy;
        PrintWriter out2 = new PrintWriter(new FileOutputStream( "D:/disertasi orang penting/OSD/hasil-1.txt" ));
        for(int i = 1; i  <=  reader.getNumberOfPages(); i++) {
            strategy = parser.processContent(i , new SimpleTextExtractionStrategy()); 
            String result = strategy.getResultantText(); 
            out2.println(result);
            out2.flush();
            
        }
        out2.close();
    }
    
    public static void main(String[] args ) throws Exception {
        new PdfExtract();
    }
}

这是方法PdfCopy方法的一个例子:

import java.io.FileOutputStream;

import com.itextpdf.text.Document;
import com.itextpdf.text.pdf.PdfCopy;
import com.itextpdf.text.pdf.PdfImportedPage;
import com.itextpdf.text.pdf.PdfReader;

public class TestExtractPdf {

    public static void main(String[] args) {
        try {
            String dirHasil = "D:/disertasi orang penting/OSD/hasil/";
            PdfReader reader = new PdfReader("D:/disertasi orang penting/OSD/disertasi doktor OSD.pdf");
            int n = reader.getNumberOfPages();
            System.out.println("Number of pages : " + n);
            
            for (int i = 0; i < n; i++) {
                String outfile = dirHasil + Integer.toString(i + 1) + ".pdf";
                System.out.println("Writing " + outfile);
                Document document = new Document(reader.getPageSizeWithRotation(1));
                PdfCopy copy = new PdfCopy(document, new FileOutputStream(outfile));
                document.open();
                PdfImportedPage page = copy.getImportedPage(reader, i );
                copy.addPage(page);
                document.close();
                copy.close();
            }
        } catch (Exception e) {
            System.out.println("eror");
            e.printStackTrace();
        }
    }
}

它引发了一个错误:

java.lang.IllegalArgumentException: PdfReader not opened with owner password
    at com.itextpdf.text.pdf.PdfReaderInstance.getImportedPage(PdfReaderInstance.java:80)
    at com.itextpdf.text.pdf.PdfCopy.getImportedPageImpl(PdfCopy.java:388)
    at com.itextpdf.text.pdf.PdfCopy.getImportedPage(PdfCopy.java:255)
    at fjr.cpns.kemenkeu.TestExtractPdf.main(TestExtractPdf.java:25)

标签: javapdfpasswordsitext

解决方案


Itext Pdf可以提取文本但不能使用所有者密码从pdf复制页面?

实际上,加密文件权限的 iText 5 实现有点奇怪:对于某些功能(特别是标记和页面复制),在加密文件的情况下需要所有者密码,而对于大多数其他功能则不需要。

由于 PDF 权限结构是为带有 GUI 的 PDF 查看器和编辑器设计的,而不是为编程库设计的,因此您无法在 iText 中认真实现它们。所完成的实现可以向 Adob​​e 证明,当 PDF 格式仍然是 Adob​​e 专有时,iText 确实尊重 PDF 引用的这一部分。

iText 5 自 5.0.2 版以来提供了一种方法来覆盖这些限制,只需初始化

PdfReader.unethicalreading = true;

在您制作 iText 代码的代码之前,假设您已经使用所有者密码打开了任意加密的 PDF,因此拥有完全权限。


但是,您的代码中有一个实际错误:

Itext 页码从 1 开始,即第一页编号为 1。

在您的工作文本提取中,您尊重这一点并从 1 开始:

for(int i = 1; i  <=  reader.getNumberOfPages(); i++) {
    strategy = parser.processContent(i , new SimpleTextExtractionStrategy()); 
    ...

但是,在您无法正常工作的复制代码中,您不尊重它并从 0 开始:

for (int i = 0; i < n; i++) {
    ...
    PdfImportedPage page = copy.getImportedPage(reader, i );
    ...

要解决此问题,请从 1 开始。


推荐阅读