Guardar PDF utilizando Springframework e iReport con paginado

Hola, para todos aquellos que utilizan springframework e iReport para visualizar sus reportes, les dejo un ejemplo para la visualización y guardado del reporte en el servidor.

  1. Lo primero que tendremos que hacer es extender de la clase org.springframework.web.servlet.view.jasperreports.AbstractJasperReportsSingleFormatView.
  2. En el constructor de nuestra clase especificar el tipo de contenido: setContentType("application/pdf");
  3. Sobrescribir los siguientes metodos: createExporter, useWriter y renderReport

En el método createExporter, en este método especificaremos los permisos que tendrá el reporte, en este caso lo podrán copiar, guardar e imprimir.

JRExporter jRExporter = new JRPdfExporter();
jRExporter.setParameter(JRPdfExporterParameter.IS_ENCRYPTED, Boolean.TRUE);
jRExporter.setParameter(JRPdfExporterParameter.IS_128_BIT_KEY, Boolean.TRUE);
jRExporter.setParameter(JRPdfExporterParameter.OWNER_PASSWORD, "password");
int permisos = PdfWriter.AllowPrinting | PdfWriter.AllowCopy;
jRExporter.setParameter(JRPdfExporterParameter.PERMISSIONS, permisos);
return jRExporter;

Antes de iniciar la explicación del método renderReport, hare mención de un método llamado moveTableOfContents, este método fue copiado de los ejemplos de las demos de jasperreports (http://jasperforge.org/projects/jasperreports), en la cual se especifica la creación de reportes con tablas de contenido. Les sugiero descargar el archivo japerreports-VERSION.zip y abrir el directorio demo/samples/tableofcontents para la creación de reportes con índice. El método utilizado en este ejemplo se obtuvo de la versión 3.7.5.

El método renderReport es el que utilizaremos para guardar nuestro reporte en el servidor, al igual para crear el paginado.
La siguiente línea invoca al método moveTableOfContents el cual manipulara al reporte para colocar el índice en el lugar correcto antes de ser guardado y visualizado.

populatedReport = moveTableOfContents(populatedReport);

Lo siguiente es la obtención del nombre con el cual se guardara el archivo y la ubicación física. Estos datos los obtenemos de los parámetros que se le envían al reporte, es decir. En el controlador previo de invocación del reporte, obtenemos los recursos de base de datos y asignamos parámetros al reporte. En este controlador se obtiene la dirección física de la aplicación y se asigna un nombre al reporte, el cual se agregan como parámetros para el reporte.

String nombre = "demo";
String dirApp = "/home/demo/files";
if(model != null && model.get("nombreReporte") != null){
        nombre = model.get("nombreReporte").toString();
        dirApp = model.get("urlApp").toString();
}

La siguiente línea de código invocara a un método recursivo que verificara la existencia del directorio y en caso de que no exista la creara.

creaDirectorio(dirApp + "/archivos/reportes/");

Y finalmente el llamado del método que guardara nuestro reporte en disco.

JasperExportManager.exportReportToPdfFile(populatedReport, dirApp + "/archivos/reportes/" + nombre + ".pdf");

El llamado en el views será de la siguiente manera:

<bean id="reporteDemoSave" class="DemoReport">
        <property name="url">
                <value>/reportes/reporteDemo.jrxml</value>
        </property>
        <property name="subReportUrls">
                <map>
                        <entry key="subreporteIndice" value="/reportes/Indice.jrxml"/>
                </map>
        </property>
</bean>

A continuación les dejo todo el código completo de este ejemplo. Saludos. Dios los bendiga.

import java.io.File;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletResponse;

import net.sf.jasperreports.engine.JRExporter;
import net.sf.jasperreports.engine.JRPrintElement;
import net.sf.jasperreports.engine.JRPrintPage;
import net.sf.jasperreports.engine.JRPrintText;
import net.sf.jasperreports.engine.JasperExportManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.export.JRPdfExporter;
import net.sf.jasperreports.engine.export.JRPdfExporterParameter;

import org.springframework.web.servlet.view.jasperreports.AbstractJasperReportsSingleFormatView;

import com.lowagie.text.pdf.PdfWriter;

public class DemoReport extends AbstractJasperReportsSingleFormatView {
        public DemoReport(){
                setContentType("application/pdf");
        }

        @Override
        protected JRExporter createExporter() {
                return getJRExporter();
        }

        @Override
        protected boolean useWriter() {
                return false;
        }
       
        @Override
        protected void renderReport(JasperPrint populatedReport, Map model,
                        HttpServletResponse response) throws Exception {
                populatedReport = moveTableOfContents(populatedReport);
                String nombre = "";
                String dirApp = "";
                if(model != null && model.get("nombreReporte") != null){
                        nombre = model.get("nombreReporte").toString();
                        dirApp = model.get("urlApp").toString();
                }
                creaDirectorio(dirApp + "/archivos/reportes/");
                JasperExportManager.exportReportToPdfFile(populatedReport, dirApp + "/archivos/reportes/" + nombre + ".pdf");
                super.renderReport(populatedReport, model, response);
        }
       
        public JRExporter getJRExporter(){
                JRExporter jRExporter = new JRPdfExporter();
                jRExporter.setParameter(JRPdfExporterParameter.IS_ENCRYPTED, Boolean.TRUE);
                jRExporter.setParameter(JRPdfExporterParameter.IS_128_BIT_KEY, Boolean.TRUE);
                jRExporter.setParameter(JRPdfExporterParameter.OWNER_PASSWORD, "password");
                int permisos = PdfWriter.AllowPrinting | PdfWriter.AllowCopy;
                jRExporter.setParameter(JRPdfExporterParameter.PERMISSIONS, permisos);
               
                return jRExporter;
        }
       
        private static JasperPrint moveTableOfContents(JasperPrint jasperPrint){
                if (jasperPrint != null){
                        List pages = jasperPrint.getPages();
                        if (pages != null && pages.size() > 0){
                                String key = "HIDDEN TEXT TO MARK THE BEGINNING OF THE TABEL OF CONTENTS";
                                JRPrintPage page = null;
                                Collection elements = null;
                                Iterator it = null;
                                JRPrintElement element = null;
                                int i = pages.size() - 1;
                                boolean isFound = false;
                                while(i >= 0 && !isFound){
                                        page = (JRPrintPage)pages.get(i);
                                        elements = page.getElements();

                                        if (elements != null && elements.size() > 0){
                                                it = elements.iterator();
                                               
                                                while(it.hasNext() && !isFound){
                                                        element = (JRPrintElement)it.next();
                                                        if (element instanceof JRPrintText){
                                                                if ( key.equals( ((JRPrintText)element).getText() ) ){
                                                                        isFound = true;
                                                                        break;
                                                                }
                                                        }
                                                }
                                        }
                                        i--;
                                }
                               
                                if (isFound){
                                        for(int j = i + 1; j < pages.size(); j++){
                                                jasperPrint.addPage(j - i - 1, jasperPrint.removePage(j));
                                        }
                                }
                        }
                }
               
                return jasperPrint;
        }
       
        private void creaDirectorio(String directorio){
                String url_nex = directorio.substring( 0,  directorio.lastIndexOf( "/" ) );
                File archivo = new File( url_nex );
                if( ! archivo.isDirectory() ){
                        if( ! archivo.mkdir() ){
                                creaDirectorio( url_nex );
                        }
                        creaDirectorio( directorio );
                }
        }
       
}

Comentarios

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.
Imagen de AlexSnake

Excelente aporte

Desde que librerias de spring y jasper podemos hace uso de ese código???

Imagen de VictorManuel

¿?

import org.springframework.web.servlet.view.jasperreports.AbstractJasperReportsSingleFormatView;

Librerias

La version de Spring utilizada para los ejemplos es la 2.5.5 y la del iReport es la 2.5

Librerias

Es correcto la importacion