Java:PDF 页面预览错误,应为外部参照
Java : PDF page preview error, expected xref
我正在尝试为 Ballasamic Mockups 创建的 PDF 文件创建预览。大约 50% 的时间,我没有得到预览并收到外部参照缺失错误。我做错了什么?
错误日志:
com.sun.pdfview.PDFParseException: Expected 'xref' at start of table
at com.sun.pdfview.PDFFile.readTrailer(PDFFile.java:974)
at com.sun.pdfview.PDFFile.parseFile(PDFFile.java:1175)
at com.sun.pdfview.PDFFile.<init>(PDFFile.java:126)
at com.sun.pdfview.PDFFile.<init>(PDFFile.java:102)
代码:
private byte[] onlyCreatePdfPreview(String path, int attachId) {
try {
File file = new File(path);
RandomAccessFile raf = new RandomAccessFile(file, "r");
FileChannel channel = raf.getChannel();
ByteBuffer buf = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size());
PDFFile pdffile = new com.sun.pdfview.PDFFile(buf);
PDFPage page = pdffile.getPage(0);
Rectangle rect = new Rectangle(0, 0,
(int) page.getBBox().getWidth(),
(int) page.getBBox().getHeight());
java.awt.Image img = page.getImage(
rect.width, rect.height, //width & height
rect, // clip rect
null, // null for the ImageObserver
true, // fill background with white
true // block until drawing is done
);
BufferedImage buffered = toBufferedImage(img);
buffered = Scalr.resize(buffered, Scalr.Method.ULTRA_QUALITY, 400, 250);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(buffered, "png", baos);
baos.flush();
return baos.toByteArray();
} catch (Exception e) {
e.printStackTrace();
}
}
我做错了什么?谢谢你。
最终工作代码
try {
String pdfPath = zipLocation + String.valueOf(new BigInteger(130, random).toString(32));
PdfReader reader = new PdfReader(path);
PdfStamper pdfStamper = new PdfStamper(reader,new FileOutputStream(pdfPath));
pdfStamper.getWriter().setPdfVersion(PdfWriter.PDF_VERSION_1_4);
pdfStamper.close();
reader.close();
RandomAccessFile raf = new RandomAccessFile(pdfPath, "r");
FileChannel channel = raf.getChannel();
ByteBuffer buf = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size());
PDFFile pdffile = new com.sun.pdfview.PDFFile(buf);
PDFPage page = pdffile.getPage(0);
Rectangle rect = new Rectangle(0, 0,
(int) page.getBBox().getWidth(),
(int) page.getBBox().getHeight());
java.awt.Image img = page.getImage(
rect.width, rect.height, //width & height
rect, // clip rect
null, // null for the ImageObserver
true, // fill background with white
true // block until drawing is done
);
BufferedImage buffered = toBufferedImage(img);
buffered = Scalr.resize(buffered, Scalr.Method.ULTRA_QUALITY, 400, 250);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(buffered, "png", baos);
baos.flush();
return baos.toByteArray();
}//catch block
(此答案从对最终导致解决方案的问题的评论中收集信息。)
显然 com.sun.pdfview.PDFFile
期望交叉引用以 xref 开头。但是这种期望只对 PDF 参考之后的 PDF 有意义,直到 2001 年 11 月发布的修订版 3(1.4 版);遵循后来的参考甚至 ISO 32000 标准(第 1 部分或第 2 部分)的 PDF 可以选择使用交叉引用流(以对象编号开头)而不是交叉引用 table(以 外部参照).
因此,人们应该转而使用遵循比 15 年以上旧版本更新的规范的软件,或者必须转换自己的 PDF 以遵循旧规范,至少表面上是这样。
可以手动转换(例如使用 Adobe Acrobat)或自动转换(例如使用 iText)。 (这些示例软件产品确实只是示例,其他产品也可以用于此任务。)
如果使用当前的 iText 5 版本,转换如下所示:
PdfReader reader = new PdfReader(SOURCE);
PdfStamper stamper = new PdfStamper(reader, DEST);
stamper.getWriter().setPdfVersion(PdfWriter.PDF_VERSION_1_4);
stamper.close();
reader.close();
并且必须注意,如果 SOURCE
是文件名或随机访问文件,则 DEST
不能是同一文件的文件输出流。否则,在 PdfStamper
有机会将其全部复制到其输出之前,原始文件将被截断。
我正在尝试为 Ballasamic Mockups 创建的 PDF 文件创建预览。大约 50% 的时间,我没有得到预览并收到外部参照缺失错误。我做错了什么?
错误日志:
com.sun.pdfview.PDFParseException: Expected 'xref' at start of table
at com.sun.pdfview.PDFFile.readTrailer(PDFFile.java:974)
at com.sun.pdfview.PDFFile.parseFile(PDFFile.java:1175)
at com.sun.pdfview.PDFFile.<init>(PDFFile.java:126)
at com.sun.pdfview.PDFFile.<init>(PDFFile.java:102)
代码:
private byte[] onlyCreatePdfPreview(String path, int attachId) {
try {
File file = new File(path);
RandomAccessFile raf = new RandomAccessFile(file, "r");
FileChannel channel = raf.getChannel();
ByteBuffer buf = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size());
PDFFile pdffile = new com.sun.pdfview.PDFFile(buf);
PDFPage page = pdffile.getPage(0);
Rectangle rect = new Rectangle(0, 0,
(int) page.getBBox().getWidth(),
(int) page.getBBox().getHeight());
java.awt.Image img = page.getImage(
rect.width, rect.height, //width & height
rect, // clip rect
null, // null for the ImageObserver
true, // fill background with white
true // block until drawing is done
);
BufferedImage buffered = toBufferedImage(img);
buffered = Scalr.resize(buffered, Scalr.Method.ULTRA_QUALITY, 400, 250);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(buffered, "png", baos);
baos.flush();
return baos.toByteArray();
} catch (Exception e) {
e.printStackTrace();
}
}
我做错了什么?谢谢你。
最终工作代码
try {
String pdfPath = zipLocation + String.valueOf(new BigInteger(130, random).toString(32));
PdfReader reader = new PdfReader(path);
PdfStamper pdfStamper = new PdfStamper(reader,new FileOutputStream(pdfPath));
pdfStamper.getWriter().setPdfVersion(PdfWriter.PDF_VERSION_1_4);
pdfStamper.close();
reader.close();
RandomAccessFile raf = new RandomAccessFile(pdfPath, "r");
FileChannel channel = raf.getChannel();
ByteBuffer buf = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size());
PDFFile pdffile = new com.sun.pdfview.PDFFile(buf);
PDFPage page = pdffile.getPage(0);
Rectangle rect = new Rectangle(0, 0,
(int) page.getBBox().getWidth(),
(int) page.getBBox().getHeight());
java.awt.Image img = page.getImage(
rect.width, rect.height, //width & height
rect, // clip rect
null, // null for the ImageObserver
true, // fill background with white
true // block until drawing is done
);
BufferedImage buffered = toBufferedImage(img);
buffered = Scalr.resize(buffered, Scalr.Method.ULTRA_QUALITY, 400, 250);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(buffered, "png", baos);
baos.flush();
return baos.toByteArray();
}//catch block
(此答案从对最终导致解决方案的问题的评论中收集信息。)
显然 com.sun.pdfview.PDFFile
期望交叉引用以 xref 开头。但是这种期望只对 PDF 参考之后的 PDF 有意义,直到 2001 年 11 月发布的修订版 3(1.4 版);遵循后来的参考甚至 ISO 32000 标准(第 1 部分或第 2 部分)的 PDF 可以选择使用交叉引用流(以对象编号开头)而不是交叉引用 table(以 外部参照).
因此,人们应该转而使用遵循比 15 年以上旧版本更新的规范的软件,或者必须转换自己的 PDF 以遵循旧规范,至少表面上是这样。
可以手动转换(例如使用 Adobe Acrobat)或自动转换(例如使用 iText)。 (这些示例软件产品确实只是示例,其他产品也可以用于此任务。)
如果使用当前的 iText 5 版本,转换如下所示:
PdfReader reader = new PdfReader(SOURCE);
PdfStamper stamper = new PdfStamper(reader, DEST);
stamper.getWriter().setPdfVersion(PdfWriter.PDF_VERSION_1_4);
stamper.close();
reader.close();
并且必须注意,如果 SOURCE
是文件名或随机访问文件,则 DEST
不能是同一文件的文件输出流。否则,在 PdfStamper
有机会将其全部复制到其输出之前,原始文件将被截断。