Экспорт в один HTML со встроенными изображениями с помощью отчета Jasper
может ли отчет Jasper экспортировать в один HTML со встроенными изображениями?
У меня есть вывод отчетов jasper в виде одного файла Excel, PDF, RTF. Но многоигровые HTML-файлы. Мне сложно управлять не одним файлом отчета, а многими файлами и папками в HTML-корпусе.
5 ответов
Я не думаю, что отчеты jasper встроены в поддержку этого, поэтому вам придется развернуть свою собственную реализацию. Вы можете использовать эту технику для встраивания в них изображений.
<img src="data:image/png;base64,iVBORw0K... " />
поэтому сначала вы должны использовать синтаксический анализатор xml java, чтобы найти все теги изображений в html http://www.mkyong.com/tutorials/java-xml-tutorials/. Затем вы прочитаете все файлы, конвертируете их в строку base64http://www.xinotes.org/notes/note/736/ и замените img's src с вышеуказанным форматом.  
решение:
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());
    }
}
я боролся с этим в течение последних нескольких дней и, наконец, решил это. Мои отчеты работают в веб-среде, поэтому я смог использовать net.sf.jasperreports.j2ee.servlets.ImageServlet для обслуживания изображений. Это требует некоторой настройки.
- 
использовать JRImageRendererдля отображения изображений в самом отчете:<image ... > ... <imageExpression> <![CDATA[net.sf.jasperreports.engine.JRImageRenderer.getInstance($F{image_data})]]> </imageExpression> </image>здесь $F{image_data}- это двоичные данные изображения.
- 
при экспорте отчета, назначить 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" />.
- 
теперь вам нужно активировать ImageServlet, поэтому он может перехватывать и выполнять запросы изображения. Добавьте следующий блок в ваш :<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. 
- 
последнее, что нужно сделать, это добавить JasperPrintобъект для сеанса, поэтомуImageServletзнает, какой образ служить. В JSP это можно сделать так:JasperPrint jasperPrint = ... HttpSession session = (HttpSession) FacesContext.getCurrentInstance().getExternalContext().getSession(true); session.setAttribute(ImageServlet.DEFAULT_JASPER_PRINT_SESSION_ATTRIBUTE, jasperPrint);
теперь это должен работать.
Как отметил Илья, до недавнего времени uri данных не был перекрестно совместим, поэтому вам пришлось сохранить несколько файлов. Возможно, потребуется подать запрос на улучшение с помощью Jasper, чтобы запросить возможность сохранения html как одного файла со встроенными uris данных
небольшое улучшение к решению Дэйва Джарвиса.
вместо жесткого кодирования типа 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 );
