Primefaces dataExporter - 在没有页脚的新窗口中内联PDF

时间:2013-01-17 13:28:49

标签: jsf-2 primefaces

我尝试使用Primefaces的dataExporter组件。我有两个问题(现在):

  1. datatable的列页脚中,我有一个p:commandButton。我发生的事情是,当我将带有dataExporter的数据表导出为PDF时,我可以看到它向PDF添加了列页脚并写了类似这样的内容:javax.faces.component.UIPanel@9e08b9(它只是调用了toString { {1}}我想)。有没有办法指示UIComponent忽略列页脚?

  2. 我想尝试以某种方式打开带有生成PDF的新窗口,并在新页面上显示PDF内联。我不会看到下载文件提示。这可能吗?

1 个答案:

答案 0 :(得分:0)

过了一段时间,编码我终于成功完成了这项工作。 Primefaces没有包含这个函数,所以我必须稍微改写默认行为。

首先,我创建了自定义PDFExporter以跳过页脚打印:

import java.io.ByteArrayOutputStream;
import java.io.IOException;

import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;

import org.primefaces.component.datatable.DataTable;
import org.primefaces.component.export.PDFExporter;

import com.lowagie.text.DocumentException;
import com.lowagie.text.pdf.PdfPTable;

public class CustomPDFExporter extends PDFExporter {

    @Override
    protected void addColumnFacets(DataTable table, PdfPTable pdfTable,
            ColumnType columnType) {
        if (columnType == ColumnType.HEADER) {
            super.addColumnFacets(table, pdfTable, columnType);
        }
    }

    @Override
    protected void writePDFToResponse(ExternalContext externalContext,
            ByteArrayOutputStream baos, String fileName) throws IOException,
            DocumentException {

        FacesContext.getCurrentInstance().getExternalContext().getSessionMap()
                .put("reportBytes", baos.toByteArray());
        FacesContext.getCurrentInstance().getExternalContext().getSessionMap()
                .put("reportName", fileName);
    }

}

如您所见,会话中添加了报告数据。

现在应该重写Primefaces的DataExporter

import java.io.IOException;

import javax.el.ELContext;
import javax.el.MethodExpression;
import javax.el.ValueExpression;
import javax.faces.FacesException;
import javax.faces.component.StateHolder;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import javax.faces.event.ActionListener;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;

import org.primefaces.component.datatable.DataTable;
import org.primefaces.component.export.CSVExporter;
import org.primefaces.component.export.Exporter;
import org.primefaces.component.export.ExporterType;
import org.primefaces.component.export.XMLExporter;
import org.primefaces.context.RequestContext;

import asw.iis.common.ui.beans.DatatableBackingBean;

public class CustomDataExporter implements ActionListener, StateHolder {

    private ValueExpression target;
    private ValueExpression type;
    private ValueExpression fileName;
    private ValueExpression encoding;
    private MethodExpression preProcessor;
    private MethodExpression postProcessor;
    private DatatableBackingBean<?> datatableBB;

    public CustomDataExporter() {}

    public CustomDataExporter(ValueExpression target, ValueExpression type, ValueExpression fileName, ValueExpression encoding,
            MethodExpression preProcessor, MethodExpression postProcessor, DatatableBackingBean<?> datatableBB) {
        this.target = target;
        this.type = type;
        this.fileName = fileName;
        this.encoding = encoding;
        this.preProcessor = preProcessor;
        this.postProcessor = postProcessor;
        this.datatableBB = datatableBB;
    }

    public void processAction(ActionEvent event) {
        FacesContext context = FacesContext.getCurrentInstance();
        try {
            datatableBB.stampaPreProcess();
            ELContext elContext = context.getELContext();

            String tableId = (String) target.getValue(elContext);
            String exportAs = (String) type.getValue(elContext);
            String outputFileName = (String) fileName.getValue(elContext);

            String encodingType = "UTF-8";
            if(encoding != null) {
                encodingType = (String) encoding.getValue(elContext);
            }

            try {
                Exporter exporter;
                ExporterType exporterType = ExporterType.valueOf(exportAs.toUpperCase());
                switch(exporterType) {
                case XLS:
                    exporter = new ExcelExporter();
                    break;

                case PDF:
                    exporter = new CustomPDFExporter();
                    break; 

                case CSV:
                    exporter = new CSVExporter();
                    break; 

                case XML:
                    exporter = new XMLExporter();
                    break;

                default:
                    exporter = new CustomPDFExporter();
                    break;
                }

                UIComponent component = event.getComponent().findComponent(tableId);
                if(component == null) {
                    throw new FacesException("Cannot find component \"" + tableId + "\" in view.");
                }

                if(!(component instanceof DataTable)) {
                    throw new FacesException("Unsupported datasource target:\"" + component.getClass().getName() + "\", exporter must target a PrimeFaces DataTable.");
                }

                DataTable table = (DataTable) component;
                exporter.export(context, table, outputFileName, false, false, encodingType, preProcessor, postProcessor);

                if ("pdf".equals(exportAs)) {
                    String path = ((ServletContext)(FacesContext.getCurrentInstance().getExternalContext().getContext())).getContextPath();
                    RequestContext.getCurrentInstance().execute("window.open('" + path + "/report.pdf', '_blank', 'dependent=yes, menubar=no, toolbar=no')");
                } else {
                    context.responseComplete();
                }
            } 
            catch (IOException e) {
                throw new FacesException(e);
            }
        }
        finally {
            ((HttpServletRequest) context.getExternalContext().getRequest()).removeAttribute("vrstaStampe");
            datatableBB.stampaPostProcess();
        }
    }

    public boolean isTransient() {
        return false;
    }

    public void setTransient(boolean value) {
    }

    public void restoreState(FacesContext context, Object state) {
        Object values[] = (Object[]) state;

        target = (ValueExpression) values[0];
        type = (ValueExpression) values[1];
        fileName = (ValueExpression) values[2];
        preProcessor = (MethodExpression) values[3];
        postProcessor = (MethodExpression) values[4];
        encoding = (ValueExpression) values[5];
        datatableBB = (DatatableBackingBean<?>) values[6];
    }

    public Object saveState(FacesContext context) {
        Object values[] = new Object[7];

        values[0] = target;
        values[1] = type;
        values[2] = fileName;
        values[3] = preProcessor;
        values[4] = postProcessor;
        values[5] = encoding;
        values[6] = datatableBB;

        return ((Object[]) values);
    }
}

此处的主要工作是实例化CustomPDFExporter,并在报告类型为PDF时打开新窗口。

现在我编写了简单的Servlet来处理此请求并打印报告数据:

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/report.pdf")
public class PdfReportServlet extends HttpServlet {

    private static final long serialVersionUID = 1L;

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        byte[] b = (byte[]) req.getSession().getAttribute("reportBytes");
        if (b == null) {
            b = new byte[0];
        }
        resp.setContentType("application/pdf");
        resp.setContentLength(b.length);
        resp.getOutputStream().write(b);
        req.getSession().removeAttribute("reportBytes");
    }
}

这将配置HTTP标头,并将报告的字节打印到输出流。它还会从会话中删除报告字节。

最后,当我从动态创建的菜单按钮处理此打印时,我在代码中添加了此动作侦听器:

MenuItem item = ...;
ELContext el = FacesContext.getCurrentInstance().getELContext();
ExpressionFactory ef = FacesContext.getCurrentInstance().getApplication().getExpressionFactory();
ValueExpression typeEL = ef.createValueExpression(el, "#{startBean.reportType}", String.class);
ValueExpression fileEL = ef.createValueExpression(el, datasource, String.class);
ValueExpression targetEL = ef.createValueExpression(el, ":" + datatableId + ":datatableForm:datatable", String.class);
ValueExpression encodingEL = ef.createValueExpression(el, "ISO-8859-2", String.class);
CustomDataExporter de = new CustomDataExporter(targetEL, typeEL, fileEL, encodingEL, null, null, this);
item.setAjax(true);
item.addActionListener(de);