Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java : PDF page preview error, expected xref

I am trying to create a preview for PDF files which are created by Ballasamic Mockups. Around 50% of the time, I am not getting a preview and getting xref missing error. What am I doing wrong?

Error log :

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)

Code :

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();
    }
}

What am I doing wrong? Thank you.

Final Working code

      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
like image 318
We are Borg Avatar asked Dec 01 '25 06:12

We are Borg


1 Answers

(This answer collects information from comments to the question which eventually led to a solution.)

Apparently com.sun.pdfview.PDFFile expects the cross references to start with xref. But this expectation only makes sense for PDFs following a PDF Reference up to revision 3 (version 1.4) published November 2001; PDFs following a later Reference or even the ISO 32000 standard (part 1 or 2) have the choice of using a cross reference stream (starting with an object number) instead of a cross reference table (starting with xref).

Thus, one should switch to using software following newer specifications than some more than 15 years old version or one has to convert one's PDFs to follow the old specifications, at least on the surface.

One can convert manually (e.g. using Adobe Acrobat) or automatized (e.g. using iText). (These examples software products really are only examples, other products can also be used for this task.)

If using a current iText 5 version, the conversion looks like this:

PdfReader reader = new PdfReader(SOURCE);
PdfStamper stamper = new PdfStamper(reader, DEST);
stamper.getWriter().setPdfVersion(PdfWriter.PDF_VERSION_1_4);
stamper.close();
reader.close();

And one has to take care that if SOURCE is a file name or a random access file, DEST must not be a file output stream to the same file. Otherwise the original file is truncated before the PdfStamper had a chance to copy it all to its output.

like image 66
mkl Avatar answered Dec 02 '25 20:12

mkl