Java: ошибка просмотра страницы PDF, ожидаемая внешняя ссылка

Я пытаюсь создать предварительный просмотр для PDF-файлов, созданных Ballasamic Mockups. Примерно в 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

1 ответ

Решение

(Этот ответ собирает информацию из комментариев к вопросу, которая в конечном итоге привела к решению.)

По-видимому com.sun.pdfview.PDFFile ожидает, что перекрестные ссылки начнутся с xref. Но это ожидание имеет смысл только для PDF-файлов после PDF-справки до версии 3 (версия 1.4), опубликованной в ноябре 2001 года; В PDF-файлах, следующих за более поздними ссылками или даже стандартом ISO 32000 (часть 1 или 2), можно использовать поток перекрестных ссылок (начиная с номера объекта) вместо таблицы перекрестных ссылок (начиная с 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 был шанс скопировать все это на свой выход.

Другие вопросы по тегам