【发布时间】:2018-04-05 10:37:29
【问题描述】:
我正在研究 Java PDF 库。
我试过了
org.apache.pdfbox
File file = new File("file.pdf");
PDDocument document = PDDocument.load(file);
// Instantiate PDFTextStripper class
PDFTextStripper pdfStripper = new PDFTextStripper();
// Retrieving text from PDF document
String text = pdfStripper.getText(document);
System.out.println(text);
// Closing the document
document.close();
com.itextpdf.text.pdf
public static final String SRC = "file.pdf";
public static final String DEST = "streams";
public static void main(final String[] args) throws IOException {
File file = new File(DEST);
new BruteForce().parse(SRC, DEST);
}
public void parse(final String src, final String dest) throws IOException {
PdfReader reader = new PdfReader(src);
PdfObject obj;
for (int i = 1; i <= reader.getXrefSize(); i++) {
obj = reader.getPdfObject(i);
if ((obj != null) && obj.isStream()) {
PRStream stream = (PRStream) obj;
byte[] b;
try {
b = PdfReader.getStreamBytes(stream);
} catch (UnsupportedPdfException e) {
b = PdfReader.getStreamBytesRaw(stream);
}
FileOutputStream fos = new FileOutputStream(String.format(dest, i));
fos.write(b);
fos.flush();
fos.close();
} else {
final PdfDictionary pdfDictionary = (PdfDictionary) obj;
System.out.println("\t>>>>> " + pdfDictionary + "\t\t" + pdfDictionary.getKeys());
final Set<PdfName> pdfNames = pdfDictionary.getKeys();
for (final PdfName pdfName : pdfNames) {
final PdfObject pdfObject = pdfDictionary.get(pdfName);
final int type = pdfObject.type();
switch (type) {
case PdfObject.NULL:
System.out.println("\t NULL " + pdfObject);
break;
case PdfObject.BOOLEAN:
System.out.println("\t BOOLEAN " + pdfObject);
break;
case PdfObject.NUMBER:
System.out.println("\t NUMBER " + pdfObject);
break;
case PdfObject.STRING:
System.out.println("\t STRING " + pdfObject);
break;
case PdfObject.NAME:
System.out.println("\t NAME " + pdfObject);
break;
case PdfObject.ARRAY:
System.out.println("\t ARRAY " + pdfObject);
break;
case PdfObject.DICTIONARY:
System.out.println("\t DICTIONARY " + ((PdfDictionary)pdfObject).getKeys());
break;
case PdfObject.STREAM:
System.out.println("\t STREAM " + pdfObject);
break;
case PdfObject.INDIRECT:
System.out.println("\t INDIRECT " +pdfObject.getIndRef());
break;
default:
}
System.out.println("\t\t--- " + pdfObject.type());
}
}
}
}
com.snowtide.pdf
String pdfFilePath = "file.pdf";
Document pdf = PDF.open(pdfFilePath);
final List<Annotation> annotations = pdf.getAllAnnotations();
for (final Annotation annotation : annotations) {
System.out.println(annotation.pageNumber());
}
System.out.println(pdf.getAttributeMap());
System.out.println(pdf.getAttributeKeys());
System.out.println("=============================");
StringBuilder text = new StringBuilder(1024);
pdf.pipe(new OutputTarget(text));
pdf.close();
System.out.println(text);
我可以提取所有可见的 PDF 内容,包括链接、文本和图像,除了出现在每个页面上的“水印”。
PDF 文档可以包含“无法访问”的内容吗?
有没有办法从 PDF 文件中提取 ALL 内容?
更新
认为“水印”是我尝试此代码的图像
File fileW = new File("file.pdf");
PDDocument document = PDDocument.load(fileW);
PDPageTree list = document.getPages();
for (PDPage page : list) {
PDResources pdResources = page.getResources();
for (COSName c : pdResources.getXObjectNames()) {
System.out.println("????? ::>>>" + c);
PDXObject o = pdResources.getXObject(c);
if (o instanceof org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject) {
File file = new File("Temp/" + System.nanoTime() + ".png");
ImageIO.write(((org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject) o).getImage(), "png", file);
} else {
}
}
}
PDF 确实包含作者的图像,但是这种方法无法达到“水印”。
【问题讨论】:
-
可能水印是图片。您看到文本,但没有字符,只有像素。也许水印是在不使用字体的情况下绘制的;即:字形的形状是使用 PDF 语法绘制的。您可以提取路径构建和路径绘制操作流,但如果您不了解 PDF 语法,您将无法理解它。也许水印是作为注释添加的,也许你只看页面内容而忘记了注释。由于我可以给你三个猜测(可能还有更多原因),我认为你的问题太笼统了,应该结束。
-
我建议您使用 PDFDebugger 或 RUPS 查看 PDF,看看它是由什么组成的。 PDF 中的内容比您提到的对象还要多。例如,流可以包含运算符及其参数。
-
不,wartermark 不一定是图像。它可以是文本或矢量图形。
-
那么最好分享 PDF 以调查这是否是一个错误。
-
“接受的文章文本”未绘制为文本。相反,字形的形状是使用 PDF 语法绘制的,正如 @Bruno 已经推测的那样,即它们是页面内容流中的 MoveTo、LineTo、CurveTo 和 Fill 指令的 blob,很容易找到RUPS 或 PDFDebugger。当我从兽医那里收集我们的一只狗回来时,我可以写一些细节。