2017-06-19 65 views
1

我想創建一個由Ballasamic Mockups創建的PDF文件的預覽。大約50%的時間,我沒有得到預覽,並獲得外部參照丟失錯誤。我究竟做錯了什麼?Java:PDF頁面預覽錯誤,預計外部參照

錯誤日誌:

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 
+0

顯然'com.sun.pdfview.PDFFile'需要** xref **的交叉引用。但是,這種期望只有在PDF參考文獻到2001年11月發佈的修訂版3(版本1.4)之後纔有意義;以後的參考文獻或甚至ISO 32000標準(第1或2部分)中的PDF可選擇使用交叉參考流(以對象編號開始)而不是交叉參考表(以** xref **開頭)。因此,您應該切換到使用新版本以上的軟件,而不是超過15年以上的版本。 – mkl

+0

@mkl這是在Windows 10上運行的軟件的最新版本。任何想法如何手動設置此元素?謝謝。 –

+0

您必須通過加載並保存PDF版本1.4兼容性來預處理PDF。您可以手動(例如使用Adobe Acrobat)或自動化(例如使用iText)來完成此操作。 – mkl

回答

2

(這個答案從評論的問題,最終導致一個解決方案收集的信息。)

顯然com.sun.pdfview.PDFFile預計交叉引用下手xref。但是這種期望只有在PDF參考文獻到2001年11月發佈的修訂版3(1.4版)之後纔有意義;在後面的參考文獻或甚至ISO 32000標準(第1或2部分)之後的PDF可以選擇使用交叉參考流(以對象編號開始)而不是交叉參考表(從xref開始)。

因此,應該切換到使用軟件遵循比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有機會將其全部複製到其輸出之前,原始文件會被截斷。