Friday, October 28, 2011

Using Batik Rasterizer in Java

In this example will create a exporting server for Highchart in Java. Since the default example is in PHP, and I'm using Java and tomcat as my web server.

I convert the PHP exporting script example to Java servlet code.

public class ReportExporter extends HttpServlet {

    protected void doPost(HttpServletRequest request, 

                          HttpServletResponse response)
            throws ServletException, IOException {

        ServletContext application = this.getServletContext();

        String type = request.getParameter("type");
        String svg = request.getParameter("svg");
        String filename = request.getParameter("filename");
       
        System.out.println("type: " + type);
        System.out.println("svg: " + svg);
        System.out.println("filename: " + filename);
        System.out.println("width: " + request.getParameter("width"));

        if (filename == null && filename.equals("")) {
            filename = "chart";
        }

        String typeString = "";
        String ext = "";
        String outFile = "";
        String width = null;
        String tempName = null;

        try {
            tempName = SecurityUtil.md5(String.valueOf(System
                    .currentTimeMillis()));
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }

        if (type.equals("image/png")) {
            typeString = "-m image/png";
            ext = "png";
        } else if (type.equals("image/jpeg")) {
            typeString = "-m image/jpeg";
            ext = "jpg";
        } else if (type.equals("application/pdf")) {
            typeString = "-m application/pdf";
            ext = "pdf";
        } else if (type.equals("image/svg+xml")) {
            ext = "svg";
        }

        outFile = "temp/" + tempName + "." + ext;
        if (!typeString.equals("")) {
            width = request.getParameter("width");
            if (width != null && !width.equals(""))
                width = "-w " + width;
        }

        // Generate temporary file
        File f = new File(application.getRealPath("/temp/" + tempName
                + ".svg"));
        IOUtil.writeToFile(f, svg);
       
        String batikPath = application.getRealPath("/WEB-INF/lib/batik-rasterizer.jar");
        String classPath = "-cp " + application.getRealPath("/WEB-INF/lib");
        String outFileFullPath = application.getRealPath(outFile);
        String tempFileFullPath = application.getRealPath("temp/"+tempName+".svg");
       
        try {
           
            // Convert SVG file into specified type
            SystemUtil.runCommand("java",classPath, "-jar",batikPath, typeString,"-d",outFileFullPath,width,tempFileFullPath);


            // Show the file to user as download
            response.setHeader("Content-disposition", "attachment; filename=" + filename + "." +ext);
            response.setHeader("Content-type", type);
           
            ServletOutputStream out = response.getOutputStream();
           
            IOUtil.fileToStream(new File(outFileFullPath), out);
           
            out.flush();
            out.close();
        } catch (Throwable e) {
            e.printStackTrace();
            response.getOutputStream().print("Error on exporting");
        }
    }
}


You will need these classes
SystemUtil
IOUtil

This example use Batik rasterizer. Please download it here. Then place it your web application folder
WEB-INF/lib/batik-rasterizer.jar
WEB-INF/lib/batik-slideshow.jar
WEB-INF/lib/batik-squiggle.jar
WEB-INF/lib/batik-svgpp.jar
WEB-INF/lib/batik-ttf2svg.jar
WEB-INF/lib/lib -> contains lib for batik (see batik distribution batik-version/lib)

5 comments:

Guy Prince said...

Thanks for your great effort but since I'm a beginner in the J2EE realm, could you please provide more detailed configuration info like how to set the exporting.url option to match your servlet location in my chart options.

Ali Irawan (Wen) said...

When using Highchart you will have such options

var chart = new Highcharts.Chart(
{
chart : {
renderTo: 'some_container'
},

exporting : {
url : 'http://www.myweb.com/exportingServlet'
}

}
);

Mohammed Abbas said...

A much simpler way of doing it. check it out

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.batik.transcoder.Transcoder;
import org.apache.batik.transcoder.TranscoderInput;
import org.apache.batik.transcoder.TranscoderOutput;
import org.apache.batik.transcoder.image.JPEGTranscoder;
import org.apache.batik.transcoder.image.PNGTranscoder;
import org.apache.fop.svg.PDFTranscoder;

public class ExportServlet extends HttpServlet {

private static final long serialVersionUID = -5921270712374007555L;

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
try
{
String type = request.getParameter("type");
String svg = request.getParameter("svg");
String filename = request.getParameter("filename");

if (filename == null && filename.equals(""))
{
filename = "chart";
}

String ext = "";
Transcoder transcoder = null;
ServletOutputStream out = response.getOutputStream();

if (!type.equals("image/svg+xml"))
{
InputStream svgInputStream = new ByteArrayInputStream(svg.getBytes());

if (type.equals("image/png"))
{
ext = "png";
transcoder = new PNGTranscoder();
}
else if (type.equals("image/jpeg"))
{
ext = "jpg";
transcoder = new JPEGTranscoder();
}
else if (type.equals("application/pdf"))
{
ext = "pdf";
transcoder = new PDFTranscoder();
}

response.setHeader("Content-disposition", "attachment; filename=" + filename + "." + ext);
response.setHeader("Content-type", type);

TranscoderInput tInput = new TranscoderInput(svgInputStream);
TranscoderOutput lOutput = new TranscoderOutput(out);
transcoder.transcode(tInput, lOutput);
}
else
{
ext = "svg";

response.setHeader("Content-disposition", "attachment; filename=" + filename + "." + ext);
response.setHeader("Content-type", type);
out.write(svg.getBytes());
}
out.flush();
out.close();
}
catch (Exception e)
{
e.printStackTrace();
}
}

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
doPost(request, response);
}
}

Anonymous said...

Hi, I came across your website and I would like to inform to everybody who's reading this blog, that Highcharts recently released a java bases export-server.

Find it here; https://github.com/highslide-software/highcharts.com/tree/master/exporting-server/java

Highsoft Solutions

Ali Irawan (Wen) said...

Great information, thanks