Экспорт в единый HTML со встроенными изображениями с использованием Jasper Report - PullRequest
8 голосов
/ 04 августа 2011

Может ли Jasper Report экспортировать в один HTML со встроенными изображениями?

У меня есть вывод отчетов Jasper в виде одного файла Excel, PDF, RTF.Но многопользовательские файлы HTML.Мне сложно управлять не одним файлом отчета, а множеством файлов и папок в случае HTML.

Ответы [ 5 ]

16 голосов
/ 07 июля 2015

Решение:

Map<String, String> images = new HashMap<>();

SimpleHtmlExporterOutput simpleHtmlExporterOutput = new SimpleHtmlExporterOutput(outputStream);
simpleHtmlExporterOutput.setImageHandler(new HtmlResourceHandler() {

            @Override
            public void handleResource(String id, byte[] data) {
                System.err.println("id" + id);
                images.put(id, "data:image/jpg;base64," + Base64.encodeBytes(data));
            }

            @Override
            public String getResourcePath(String id) {
                return images.get(id);
            }
        });

Полный код:

package com.test.report;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.util.HashMap;
import java.util.Map;

import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.JasperReport;
import net.sf.jasperreports.engine.data.JRXmlDataSource;
import net.sf.jasperreports.engine.export.HtmlExporter;
import net.sf.jasperreports.engine.export.HtmlResourceHandler;
import net.sf.jasperreports.export.SimpleExporterInput;
import net.sf.jasperreports.export.SimpleHtmlExporterOutput;
import net.sf.jasperreports.export.SimpleHtmlReportConfiguration;

import org.apache.commons.io.FileUtils;
import org.junit.Test;
import org.olap4j.impl.Base64;

import com.artech.reportservice.reports.ReportType;

public class ReportTest {
    Map<String, String> images = new HashMap<>();

    @Test
    public void test() throws Exception {
        // String outFileName = "test.html";

        String xmlFileLocation = "/Users/skozlic/dev/VacationToolProject/wokspace/ReportService/src/test/resources/machineReportTestFile.xml";

        JasperReport reportTemplate = ReportType.MPM.getReportTemplate();
        JRXmlDataSource jrxmlds = ReportType.MPM.getReportDateSource(xmlFileLocation);
        JasperPrint jasperPrint = JasperFillManager.fillReport(reportTemplate, null, jrxmlds);

        HtmlExporter exporterHTML = new HtmlExporter();
        SimpleExporterInput exporterInput = new SimpleExporterInput(jasperPrint);
        exporterHTML.setExporterInput(exporterInput);
        SimpleHtmlReportConfiguration reportExportConfiguration = new SimpleHtmlReportConfiguration();

        exporterHTML.setConfiguration(reportExportConfiguration);
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

        SimpleHtmlExporterOutput simpleHtmlExporterOutput = new SimpleHtmlExporterOutput(outputStream);
        simpleHtmlExporterOutput.setImageHandler(new HtmlResourceHandler() {

            @Override
            public void handleResource(String id, byte[] data) {
                System.err.println("id" + id);
                images.put(id, "data:image/jpg;base64," + Base64.encodeBytes(data));
            }

            @Override
            public String getResourcePath(String id) {
                return images.get(id);
            }
        });
        exporterHTML.setExporterOutput(simpleHtmlExporterOutput);

        exporterHTML.exportReport();
        FileUtils.writeByteArrayToFile(new File("test.html"), outputStream.toByteArray());

    }
}
4 голосов
/ 04 августа 2011

Я не думаю, что отчеты Jasper имеют встроенную поддержку для этого, поэтому вам придется развернуть собственную реализацию.Вы можете использовать эту технику для встраивания в них изображений.

<img src="data:image/png;base64,iVBORw0K... " />

Итак, сначала вы использовали бы XML-парсер java, чтобы найти все теги изображений в html http://www.mkyong.com/tutorials/java-xml-tutorials/. Затем вы прочитали бы всефайлы, преобразуйте их в строку base64 http://www.xinotes.org/notes/note/736/ и замените src img на вышеуказанный формат.

1 голос
/ 30 апреля 2018

Я боролся с этим последние несколько дней и наконец решил. Мои отчеты выполняются в веб-среде, поэтому я смог использовать net.sf.jasperreports.j2ee.servlets.ImageServlet для обслуживания изображений. Это требует немного настройки, хотя.

  1. Используйте JRImageRenderer для отображения изображений в самом отчете:

    <image ... >
      ...
      <imageExpression>
        <![CDATA[net.sf.jasperreports.engine.JRImageRenderer.getInstance($F{image_data})]]>
      </imageExpression>
    </image>
    

    где $F{image_data} - данные двоичного изображения.

  2. При экспорте отчета укажите WebResourceHandler в качестве обработчика ресурсов HTML.

    SimpleHtmlExporterOutput exporterOutput = new SimpleHtmlExporterOutput(byteArrayOutputStream);
    HtmlResourceHandler imageHandler = new WebHtmlResourceHandler("https://www.mywebsite.com/report/image?image={0}");
    exporterOutput.setImageHandler(imageHandler);
    exporter.setExporterOutput(exporterOutput);
    exporter.exportReport();
    

    Чтобы проверить, если теперь вы генерируете отчет в формате HTML и проверяете источник, вы должны увидеть что-то вроде <img href="http://www.mywebsite.com/report/image?image=img_0_0_2.png" />.

  3. Теперь вам нужно активировать ImageServlet, чтобы он мог перехватывать и выполнять запросы изображений. Добавьте следующий блок в Ваш web.xml файл:

    <servlet>
      <servlet-name>JasperImageServlet</servlet-name>
      <servlet-class>net.sf.jasperreports.j2ee.servlets.ImageServlet</servlet-class>
    </servlet>
    <servlet-mapping>
      <servlet-name>JasperImageServlet</servlet-name>
      <url-pattern>/report/image</url-pattern>
    </servlet-mapping>
    

    (Обратите внимание, что путь /report/image соответствует аргументу URL, который мы передали WebHtmlResourceHandler.)

    Запустите веб-сервер и попробуйте сгенерировать отчет в формате HTML еще раз. Конечно, это не сработает, но скопируйте URL-адрес изображения и вставьте его в свой браузер. Вы должны получить сообщение об ошибке от ImageServlet, что

    В сеансе HTTP не найдено документов JasperPrint.

  4. Последнее, что нужно сделать, это добавить объект JasperPrint к сеансу, чтобы ImageServlet знал, какое изображение следует обслуживать. В JSP это можно сделать так:

    JasperPrint jasperPrint = ...
    HttpSession session = (HttpSession) FacesContext.getCurrentInstance().getExternalContext().getSession(true);
    session.setAttribute(ImageServlet.DEFAULT_JASPER_PRINT_SESSION_ATTRIBUTE, jasperPrint);
    

Теперь это должно работать.

0 голосов
/ 26 июля 2017

Незначительное улучшение решения Дейва Джарвиса.

Вместо жесткого кодирования типа MIME в

images.put(id, "data:image/jpg;base64," + Base64.encodeBytes(data));

Вы можете попытаться обнаружить тип MIME следующим образом:

// Find out the mime type
final ByteArrayInputStream bis = new ByteArrayInputStream( data );
final String mimeType = URLConnection.guessContentTypeFromStream( bis );
// Convert to an embedded "data" url.
final String base64Data = "data:"+mimeType+";base64,"+Base64.encodeBytes( data );
imagesMap.put( id, base64Data );
0 голосов
/ 04 августа 2011

Как отметил ilia, до недавнего времени данные uri не были кросс-совместимы, поэтому вы ДОЛЖНЫ сохранять несколько файлов. Возможно, вы захотите подать запрос на улучшение в Jasper, чтобы запросить опцию сохранения html как одного файла со встроенными данными uris

...