четверг, 21 июня 2012 г.

Генерация pdf из java

Появилась недавно задача - добавить в pdf шаблон несколько строк, причем pdf был довольно сложный по составу. Немного поискав варианты решения, понял, есть два пути - использовать генератор с шаблонами, либо загружать готовый pdf документ и непосредственно выводить в него текст. Поняв, что первый вариант меня не устраивает по той причине, что шаблон уже в pdf формате, и рисовать его заново мне не хочется, я остановился на варианте с непосредственным выводом текста в pdf.

Первой мне попалась библиотека pdfbox. К сожалению, не удалось заставить ее корректно отображать русские буквы. Возможно, мне просто не повезло со шрифтом, который я пытался использовать, или не понравилась кодировка, не знаю. Возможно когда-нибудь я предоставлю ей второй шанс.

Следующая на очереди была iText. С помощью неё удалось решить поставленную задачу. Замеченные особенности:

  • Практически все тулзы для генерации pdf файлов внедряют в итоговый файл только subset'ы используемых шрифтов. Вывод - не нужно использовать внедренные в pdf шрифты, если не хотите получить слова с отсутствующими буквами.
  • Стандартные шрифты, например BaseFont.HELVETICA, содержат в себе только латинские символы и не могут быть использованы для вывода текста в кириллице.
  • Используйте Unicode шрифты, загружайте их из файла и внедряйте в итоговый pdf документ. Сделать это просто, вызвав BaseFont.createFont("Liberation-Sans.ttf", BaseFont.IDENTITY_H, true)
И пример использования:

    File tmp = File.createTempFile("pdf", null);
    FileOutputStream outStream = new FileOutputStream(tmp);
    Document pdDoc = new Document(PageSize.A4);
    PdfWriter writer = PdfWriter.getInstance(pdDoc, outStream);
    pdDoc.open();
    try{
        PdfContentByte cb = writer.getDirectContent();

        InputStream is = 
                    getClass().getClassLoader().getResourceAsStream("/templates/template.pdf");
        if (is == null) {
            throw new DocumentException("cannot load template");
        }

        String fontPath = "/templates/" + 
                          Config.getInstance().getString("templates.font");
        URL u = getClass().getClassLoader().getResource(fontPath);
        if(u == null){
            throw new  DocumentException("cannot load font");
        }
        // load font from resource
        BaseFont bf = BaseFont.createFont(u.getFile(), BaseFont.IDENTITY_H, true);
        PdfReader reader = new PdfReader(is);
        PdfImportedPage page = writer.getImportedPage(reader, 1);

        // Copy first page of existing PDF into output PDF
        pdDoc.newPage();
        cb.addTemplate(page, 0, 0);

        cb.saveState();

        // write  text
        cb.beginText();
        cb.setFontAndSize(bf, 10);
        cb.setTextMatrix(197, 676);
        cb.showText("some text");

        cb.setFontAndSize(bf, 7);

        cb.setTextMatrix(70, 645);
        cb.showText("smaller text");

        cb.endText();
        cb.restoreState();


        page = writer.getImportedPage(reader, 2);
        pdDoc.newPage();
        //add second page as is
        cb.addTemplate(page, 0, 0);


        page = writer.getImportedPage(reader, 3);
        pdDoc.newPage();
        //add third page as is
        cb.addTemplate(page, 0, 0);
    }finally{
        pdDoc.close();
    }

Комментариев нет:

Отправить комментарий