Отчеты Jasper PDF не соответствуют PDF / UA - PullRequest
1 голос
/ 12 июня 2019

Я хочу, чтобы PDF-файлы экспортировались с помощью Jasper PDF / UA-совместимого, но ограничения Jasper мешают мне это делать. Клиент оказывает на нас давление, чтобы мы сделали это правильно.

PDF / UA предъявляет множество требований, включая, помимо прочего, отображение названия и языка, встраивание шрифтов и добавление альтернативного текста к изображениям. До сих пор я установил все 508 тегов PDF, установил свойства для отображения названия и языка, встроенных шрифтов и добавил альтернативный текст к изображениям в Jaspersoft Studio. Я также добавил идентификатор PDF / UA к выходному PDF (т.е. после того, как PDF был создан) через Apache PDFBox. Мы используем Jaspersoft Studio v6.6.0 в сочетании с Jasper Reports Library v6.4.0 и Oracle для БД. Из того, что я прочитал, Jasper имеет ограниченные возможности в этом отношении из-за того, что itext был понижен до v2.1.7.js6 из-за проблем с лицензированием.

<jasperReport xlmns=...>
        ... // other properties
        <property name="net.sf.jasperreports.awt.ignore.missing.font" value="false"/>
        <property name="net.sf.jasperreports.export.xls.detect.cell.type" value="false"/>
        <property name="net.sf.jasperreports.export.xls.sheet.names.all" value="REPORT SHEET NAME"/>
        <property name="net.sjasperreports.default.pdf.font.name" value="Times-Roman"/>
        <property name="net.sf.jasperreports.export.xls.ignore.graphics" value="false"/>
        <property name="net.sf.jasperreports.default.pdf.embedded" value="true"/>
        <property name="net.sf.jasperreports.export.pdf.metadata.title" value="MY REPORT TITLE"/>
        <property name="net.sf.jasperreports.export.pdf.display.metadata.title" value="true"/>
        <property name="net.sf.jasperreports.export.pdf.tagged" value="true"/>
        <property name="net.sf.jasperreports.export.pdf.tag.language" value="EN-US"/>
        ... // parameters, stored proc call, headings, etc.
        <!-- Possible PDF 508 tags to be set on text fields -->
        <property name="net.sf.jasperreports.export.pdf.tag.table" value="start"/>
        <property name="net.sf.jasperreports.export.pdf.tag.th" value="full"/>
        <property name="net.sf.jasperreports.export.pdf.tag.tr" value="start">
        <property name="net.sf.jasperreports.export.pdf.tag.td" value="full">
        <property name="net.sf.jasperreports.export.pdf.tag.tr" value="end">
        <property name="net.sf.jasperreports.export.pdf.tag.table" value="start"/>
        ...
</jasperReport>
... // other imports
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.common.PDMetadata;
import org.apache.xmpbox.XMPMetadata;
import org.apache.xmpbox.schema.XMPSchema;
import org.apache.xmpbox.xml.XmpSerializer;
... // more imports

public class ReportResult {
   ... // other methods

    /*
     * @param pdf - The pdf instance created from BAOS
     * @param title - Document
     * @return BAOS containing metadata (UA-identifier, title)
     */
    private ByteArrayOutputStream appendXMPMetaData(PDDocument pdf, String title) throws TransformerException, IOException {
        XMPMetadata xmp = XMPMetadata.createXMPMetadata();
        xmp.createAndAddDublinCoreSchema();
        xmp.getDublinCoreSchema().setTitle(title);
        xmp.getDublinCoreSchema().setDescription(title);
        xmp.createAndAddPDFAExtensionSchemaWithDefaultNS();
        xmp.getPDFExtensionSchema().addNamespace("http://www.aiim.org/pdfa/ns/schema#", "pdfaSchema");
        xmp.getPDFExtensionSchema().addNamespace("http://www.aiim.org/pdfa/ns/property#", "pdfaProperty");
        xmp.getPDFExtensionSchema().addNamespace("http://www.aiim.org/pdfua/ns/id/", "pdfuaid");

        XMPSchema uaSchema = new XMPSchema(XMPMetadata.createXMPMetadata(),
                "pdfaSchema", "pdfaSchema", "pdfaSchema");
        uaSchema.setTextPropertyValue("schema", "PDF/UA Universal Accessibility Schema");
        uaSchema.setTextPropertyValue("namespaceURI", "http://www.aiim.org/pdfua/ns/id/");
        uaSchema.setTextPropertyValue("prefix", "pdfuaid");

        XMPSchema uaProp = new XMPSchema(XMPMetadata.createXMPMetadata(),"pdfaProperty", "pdfaProperty", "pdfaProperty");
        uaProp.setTextPropertyValue("name", "part");
        uaProp.setTextPropertyValue("valueType", "Integer");
        uaProp.setTextPropertyValue("category", "internal");
        uaProp.setTextPropertyValue("description", "Indicates, which part of ISO 14289 standard is followed");
        uaSchema.addUnqualifiedSequenceValue("property", uaProp);

        xmp.getPDFExtensionSchema().addBagValue("schemas", uaSchema);
        xmp.getPDFExtensionSchema().setPrefix("pdfuaid");
        xmp.getPDFExtensionSchema().setTextPropertyValue("part", "1");

        XmpSerializer serializer = new XmpSerializer();
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        serializer.serialize(xmp, baos, true);

        PDMetadata metadata = new PDMetadata(pdf);
        metadata.importXMPMetadata(baos.toByteArray());
        pdf.getDocumentCatalog().setMetadata(metadata);

        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        pdf.save(byteArrayOutputStream);
        pdf.close();

        return byteArrayOutputStream;
    } 

    protected void getJasperPDFDoc(ReportConfig reportConfig) throws IOException, TransformerException {

        List<ReportParameter> reportParams = reportConfig.getReportParams();

        ... // cookies and printer config

        Map imagesMap = new HashMap();
        request.getSession(true).setAttribute("IMAGES_MAP", imagesMap);

        ByteArrayOutputStream bs = ReportAccess.Instance.getInstance().generateJasperReport(
                getCurrentUserId(), getCurrentUserName(), reportConfig, "PDF",
                 reportParams, getTmpImageUri(),
                 imagesMap, rptTemplateLoc);

        if (bs != null) {
            if (reportConfig.doPrint) {
                response.setContentType("text/html");
            } else {
                log.debug("Got PDF report data");
                String fileName = getReportFileName(reportConfig) + ".pdf";
                response.setContentType("application/pdf");
                String dispositionProperty = "attachment; filename=" + fileName;
                response.setHeader("Content-disposition", dispositionProperty);
            }

            PDDocument pdf = PDDocument.load(new ByteArrayInputStream(bs.toByteArray()));
            ByteArrayOutputStream baosWithMetaData = appendXMPMetaData(pdf, reportConfig.getDisplayName());

            response.setHeader("Content-length", Integer.toString(baosWithMetaData.size()));
            ServletOutputStream os = response.getOutputStream();
            baosWithMetaData.writeTo(os);

            os.flush();
            os.close();
        } else {
            displayError("PDF");
        }
     }

     ... // other methods
}
/* REPORT MANAGER CLASS */
private static void generatePDFDoc(JasperPrint jasperPrint, ByteArrayOutputStream f) {

        try {

            JasperPrint jr = moveTableOfContents(jasperPrint);
            JRPdfExporter exporter  = new JRPdfExporter();
            exporter.setExporterInput(new SimpleExporterInput(jr));
            exporter.setExporterOutput(new SimpleOutputStreamExporterOutput(f));

            //configuration
            SimplePdfExporterConfiguration configuration = new SimplePdfExporterConfiguration();
            configuration.setCompressed(true);
            configuration.setTagged(true);
            configuration.setTagLanguage("EN-US");

            //set configuration
            exporter.setConfiguration(configuration);

            //export to PDF
            exporter.exportReport();
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
    }

Я заметил несколько ошибок, о которых сообщила программа проверки Preflight, а также наш клиент, перечисленных ниже:

  1. присутствует нестандартный тег
  2. Круговая ролевая карта
  3. Неизвестная ячейка привязки, добавленная в верхний левый угол каждой страницы
  4. Таблица не распознается должным образом в представлении редактора таблиц

Изображения , показывающие мои проблемы. Любая помощь в этом отношении приветствуется.

1 Ответ

0 голосов
/ 12 июля 2019

Если вы хотите сделать вещи проще, но по-другому, PD4ML v4 может быть вариантом. На странице представлен минималистичный образец: https://pd4ml.tech/pdf-ua/

Он использует доступную структуру и мета-информацию из входного HTML / CSS для создания допустимого тегированного PDF / UA.

Если цель состоит в том, чтобы пройти только проверку формата файла PDF / UA (например, с помощью программы проверки Preflight от Adobe), достаточно просто выбрать Constants.PDFUA в качестве выходного формата.

pd4ml.writePDF(fos, Constants.PDFUA);

Если цель состоит в том, чтобы создать PDF-файлы, соответствующие протоколу Маттерхорна (и пройти проверку PAC3 https://www.access -for-all.ch / en / pdf-lab / pdf-accessibility-checker-pac.html ), скорее всего, вам также необходимо выровнять входной HTML: добавить атрибуты TITLE, ALT и LANG, убедиться в согласованности структур таблиц и иерархии заголовков и т. Д.

...