Export to single HTML with embedded images using J

2020-03-01 19:53发布

Can Jasper Report export to single HTML with embedded images?

I have output of jasper reports as single Excel file, PDF, RTF. But multiplay HTML files. It trouble for me to manage not single report file, but many files and folders in HTML case.

5条回答
祖国的老花朵
2楼-- · 2020-03-01 20:36

I don't think that jasper reports has built in support for this, so you'd have to roll out your own implementation. You can use this technique to embed them images.

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

So first you'd use java's xml parser to find all the image tags in the html http://www.mkyong.com/tutorials/java-xml-tutorials/. Then you'd read all the files, convert them to base64 string http://www.xinotes.org/notes/note/736/ and replace the img's src with the above format.

查看更多
smile是对你的礼貌
3楼-- · 2020-03-01 20:48

A minor improvement to Dave Jarvis solution.

Instead of hard-coding the mime type in

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

You can try to discover the mime type like this:

// 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 );
查看更多
家丑人穷心不美
4楼-- · 2020-03-01 20:50

I was grappling with this for the last few days, and finally solved it. My reports run in a web environment, so I was able to use the net.sf.jasperreports.j2ee.servlets.ImageServlet to serve the images. This requires a bit of setting up though.

  1. Use the JRImageRenderer to render the images in the report itself:

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

    where $F{image_data} is the binary image data.

  2. When exporting the report, nominate WebResourceHandler as the HTML resource handler.

    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();
    

    To check, if you now generate an HTML report and inspect the source, you should see something like <img href="http://www.mywebsite.com/report/image?image=img_0_0_2.png" />.

  3. Now you need to activate the ImageServlet, so it can intercept and fulfill the image requests. Add the following block to your web.xml file:

    <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>
    

    (Note that the /report/image path matches the URL argument we passed to the WebHtmlResourceHandler.)

    Start the webserver and try to generate an HTML report once more. It still won't work of course, but copy the image's URL and paste it into your browser. You should get an error message from the ImageServlet that

    No JasperPrint documents found on the HTTP session.

  4. The last thing to do is to add the JasperPrint object to the session, so the ImageServlet knows which image to serve. In JSP that can be done like this:

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

Now it should work.

查看更多
老娘就宠你
5楼-- · 2020-03-01 20:55

A solution:

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);
            }
        });

Full code:

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());

    }
}
查看更多
冷血范
6楼-- · 2020-03-01 20:55

As noted by ilia, until recently data uri was not cross compatible, so you HAD to save multiple files. Might want to file an enhancement request with Jasper to request an option to save html as one file with embedded data uris

查看更多
登录 后发表回答