Jsf 如何修复只能在第二次使用的commandButton中的Primefaces文件下载?

Jsf 如何修复只能在第二次使用的commandButton中的Primefaces文件下载?,jsf,primefaces,download,Jsf,Primefaces,Download,我正在开发一个新功能,我需要它来下载从数据库查询生成的CSV文件。我在JSF2.1和JBoss6.1中使用PrimeFaces3.5。IDE是Eclipse-Oxygen 用户主要可以下载与某个月/年日期相关的员工档案。但是,当我点击下载按钮时,它在第一时间就不起作用了。奇怪的是,当再次单击按钮时,它工作正常 功能性有两个屏幕: 第一:在这个屏幕中有一个表单,用户可以通过两个按钮访问第二个屏幕。 任何一个按钮都会打开第二个屏幕。由于未来的一些功能,有两个按钮,所以现在不要介意。 按钮使用acti

我正在开发一个新功能,我需要它来下载从数据库查询生成的CSV文件。我在JSF2.1和JBoss6.1中使用PrimeFaces3.5。IDE是Eclipse-Oxygen

用户主要可以下载与某个月/年日期相关的员工档案。但是,当我点击下载按钮时,它在第一时间就不起作用了。奇怪的是,当再次单击按钮时,它工作正常

功能性有两个屏幕:

第一:在这个屏幕中有一个表单,用户可以通过两个按钮访问第二个屏幕。 任何一个按钮都会打开第二个屏幕。由于未来的一些功能,有两个按钮,所以现在不要介意。 按钮使用action标记上定义的方法的字符串返回重定向流

在第二个屏幕中,用户可以在SelectOne菜单框中选择日期,然后单击按钮。当用户这样做时,将生成csv文件

但是,如前所述,在第一次单击时,浏览器栏中会显示联系服务器的消息,但不会下载任何文件。用户第二次单击按钮时,文件被下载

没有抛出异常

我已经尝试过用h:tags而不是p:.来更改代码,将按钮放在panelGrid之外并搜索互联网,但没有成功

一些代码更改使文件在第二次屏幕加载期间生成,然后单击下载按钮。但这并不可取

第一个屏幕代码:arquivoDiariasDFI.xhtml

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:c="http://java.sun.com/jsp/jstl/core"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:p="http://primefaces.org/ui">

<h:head>
</h:head>
<h:body >

<ui:composition template="/layout/common.xhtml">

        <ui:param name="mbean" value="#{arquivoDiariasDFIManagedBean}" />
        <ui:param name="entity" value="Arquivos de Diarias - DFI" />

    <ui:define name="content">

        <h:form id="tela2" acceptcharset="ISO-8859-1">
            <h:outputScript library="javascript" name="locale-primefaces.js" />
            <p:messages id="messages" showDetail="false" autoUpdate="true" closable="true" globalOnly="false"  />

            <div class="lblFuncionalidade">#{entity}</div>

            <div>       
                    <p></p>
                    <p:panelGrid border="1" width="100%"  > 
                        <p:row style="border:0px; width:100%" columns="3"  >
                            <p:column style="border:0px; font-weight:bold; width:10%" > Mes Base:  </p:column>
                            <p:column style="border:0px; font-weight:bold; width:50%">
                                    <p:selectOneMenu id="smMesBase" filter="true" value="#{mbean.arquivoDiariasDFI.dataBase}" 
                                                 required="true" requiredMessage="Campo Obrigatorio: Mes Base" disabled="#{mbean.desabDataBase}"  >
                                    <f:selectItem itemLabel="Selecione o mes base"  />
                                    <f:selectItems value="#{mbean.datasBases}" var="dtBase" itemValue="#{dtBase}" 
                                                   itemLabel="#{dtBase}" >
                                    </f:selectItems>
                                    </p:selectOneMenu>
                            </p:column>
                            <p:column style="border:0px;" >
                                        <h:commandButton value="Gerar arquivo de integrantes" id="botaoIntegrantes"
                                            action="#{mbean.botaoArquivoFuncionarios()}" 
                                             onclick="PrimeFaces.monitorDownload(start, stop);" > 
                                            <p:fileDownload value="#{mbean.arquivo}"/> 
                                        </h:commandButton>
                            </p:column>


                        </p:row>
                    </p:panelGrid>

                    <p></p>

            <!--  -->           
            </div>
            <p:ajaxStatus onstart="statusDialog.show();" oncomplete="statusDialog.hide();" />

            <p:dialog modal="true" widgetVar="statusDialog" showHeader="false"
                      draggable="false" closable="false" resizable="false">
                <p:graphicImage value="../imagens/ajax-loader.gif" />
            </p:dialog>

        </h:form>



</ui:define>
</ui:composition>
</h:body>
</html> 

第二个屏幕代码arquivoDiariasDFI_detalhe.xhtml

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:c="http://java.sun.com/jsp/jstl/core"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:p="http://primefaces.org/ui">

<h:head>
</h:head>
<h:body >

<ui:composition template="/layout/common.xhtml">

        <ui:param name="mbean" value="#{arquivoDiariasDFIManagedBean}" />
        <ui:param name="entity" value="Arquivos de Diarias - DFI" />

    <ui:define name="content">

        <h:form id="tela2" acceptcharset="ISO-8859-1">
            <h:outputScript library="javascript" name="locale-primefaces.js" />
            <p:messages id="messages" showDetail="false" autoUpdate="true" closable="true" globalOnly="false"  />

            <div class="lblFuncionalidade">#{entity}</div>

            <div>       
                    <p></p>
                    <p:panelGrid border="1" width="100%"  > 
                        <p:row style="border:0px; width:100%" columns="3"  >
                            <p:column style="border:0px; font-weight:bold; width:10%" > Mes Base:  </p:column>
                            <p:column style="border:0px; font-weight:bold; width:50%">
                                    <p:selectOneMenu id="smMesBase" filter="true" value="#{mbean.arquivoDiariasDFI.dataBase}" 
                                                 required="true" requiredMessage="Campo Obrigatorio: Mes Base" disabled="#{mbean.desabDataBase}"  >
                                    <f:selectItem itemLabel="Selecione o mes base"  />
                                    <f:selectItems value="#{mbean.datasBases}" var="dtBase" itemValue="#{dtBase}" 
                                                   itemLabel="#{dtBase}" >
                                    </f:selectItems>
                                    </p:selectOneMenu>
                            </p:column>
                            <p:column style="border:0px;" >
                                        <h:commandButton value="Gerar arquivo de integrantes" id="botaoIntegrantes"
                                            action="#{mbean.botaoArquivoFuncionarios()}" 
                                             onclick="PrimeFaces.monitorDownload(start, stop);" > 
                                            <p:fileDownload value="#{mbean.arquivo}"/> 
                                        </h:commandButton>
                            </p:column>


                        </p:row>
                    </p:panelGrid>

                    <p></p>

            <!--  -->           
            </div>
            <p:ajaxStatus onstart="statusDialog.show();" oncomplete="statusDialog.hide();" />

            <p:dialog modal="true" widgetVar="statusDialog" showHeader="false"
                      draggable="false" closable="false" resizable="false">
                <p:graphicImage value="../imagens/ajax-loader.gif" />
            </p:dialog>

        </h:form>



</ui:define>
</ui:composition>
</h:body>
</html> 
托管bean抑制代码

package mppr.srh.dominio.bean;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;

import org.primefaces.model.DefaultStreamedContent;
import org.primefaces.model.StreamedContent;

import mppr.srh.manager.ArquivoDiariasDFIManagerLocal;
import mppr.srh.manager.FuncionarioManagerLocal;
import mppr.srh.model.ArquivoDiariasDFI;
import mppr.srh.model.Funcionario;

@ManagedBean
@SessionScoped 
public class ArquivoDiariasDFIManagedBean  {

    private static final long serialVersionUID = 1L;

    private String status = "tela1";     //Controle de tela
    private Boolean desabDataBase = false; //Controle de botão Mes Base

    private List < Funcionario > funcionarios;

    @EJB
    FuncionarioManagerLocal funcionarioManagerLocal;

    @EJB
    private ArquivoDiariasDFIManagerLocal svc; 

    private List < ArquivoDiariasDFI >  listArquivoDiariasDFI;
    private ArquivoDiariasDFI arquivoDiariasDFI;
    private List < String > datasBases;

    private StreamedContent arquivo;
    String nomeArq;



    //Métodos "padrão"
    @PostConstruct
    public void construct(){
        this.setStatus("tela1");
        listArquivoDiariasDFI = svc.retornaTodasAsDiarias();
    }

    public List<String> getDatasBases() {
        return datasBases;
    }

    public void setDatasBases(List<String> datasBases) {
        this.datasBases = datasBases;
    }

    public String getNomeArq() {
        return nomeArq;
    }

    public void setNomeArq(String nomeArq) {
        this.nomeArq = nomeArq;
    }

    public Boolean getDesabDataBase() {
        return desabDataBase;
    }

    public void setDesabDataBase(Boolean desabDataBase) {
        this.desabDataBase = desabDataBase;
    }

    public List<ArquivoDiariasDFI> getListArquivoDiariasDFI() {
        return listArquivoDiariasDFI;
    }



    public void setListArquivoDiariasDFI(List<ArquivoDiariasDFI> listArquivoDiariasDFI) {
        this.listArquivoDiariasDFI = listArquivoDiariasDFI;
    }



    public ArquivoDiariasDFI getArquivoDiariasDFI() {
        return arquivoDiariasDFI;
    }



    public void setArquivoDiariasDFI(ArquivoDiariasDFI arquivoDiariasDFI) {
        this.arquivoDiariasDFI = arquivoDiariasDFI;
    }



    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }

    public List<Funcionario> getFuncionarios() {
        return funcionarios;
    }

    public void setFuncionarios(List<Funcionario> funcionarios) {
        this.funcionarios = funcionarios;
    }

    public void setArquivo(StreamedContent arquivo) {
        this.arquivo = arquivo;
    }

    public StreamedContent getArquivo() throws IOException {

        return arquivo;

    }

    public void botaoArquivoFuncionarios() throws IOException {

        //Abre classes de escrita em arquivo
        this.nomeArq = "ListaFuncionarios" + this.arquivoDiariasDFI.getDataBase().replace("/","") + ".csv";

        File f = this.gerarArquivoFuncionarios();
        FileInputStream stream = new FileInputStream (f);

        arquivo = new DefaultStreamedContent(stream, "", nomeArq);


    }

    public File gerarArquivoFuncionarios() throws IOException { 

        File f = new File(this.nomeArq);

        FileOutputStream fos = null;
        PrintStream ps = null;

        try {

            fos = new FileOutputStream(f);
            ps = new PrintStream(fos);

            //Carrega todos os funcionários
            this.setFuncionarios(funcionarioManagerLocal.getFuncionarioAnual(1)); //Pega funcionarios com data_fim ate um ano atras

            ps.println("CPF, NOME, CARGO");

            for (Funcionario func : funcionarios) {

                ps.println(String.format("%s, %s, %s", func.getNoCpf(), func.getNmFuncionario(), func.getCargo().getDsCargo()  ));


            }
            ps.flush();

        } catch (Exception e) {
            e.printStackTrace();
        } finally {

            try {

                if (fos != null) {
                    fos.close();
                }
                if (ps != null ) {
                    ps.close();
                }

                return f;

            } catch (Exception e) {
                e.printStackTrace();
            }

        }

        return f;

    }


    //
    public String abrirTelaDeEnvio() {

        this.setDatasBases(this.carregaDatasBases());
        //Foi selecionado um registro (data base preenchida)
        if (arquivoDiariasDFI != null) {

            this.setStatus("tela2_alteracao");
            this.desabDataBase = true;

            //carrega arquivo de acordo com processamento. 


        } else {
            this.setStatus("tela2_novo");
            this.desabDataBase = false;
            arquivoDiariasDFI = new ArquivoDiariasDFI();
            arquivoDiariasDFI.setSituacao(1);
            this.setDatasBases(this.carregaDatasBases());
        }

        return "arquivoDiariasDFI_detalhe.xhtml"; //retorno para navegação.

    }   

    //Carrega lista de Meses Bases: de hoje até 1 ano atrás. 
    //Já retorna convertida para String.
    public List < String > carregaDatasBases() {

        ArrayList < String > retorno = new ArrayList<String>();

        Calendar c = Calendar.getInstance();

        c.setTime( new Date());

        Date data = c.getTime();

        retorno.add(formataMesBase(data));

        int incremento = 1;
        while (incremento <= 12) {

            c.add(Calendar.MONTH, -1 );
            data = c.getTime();
            retorno.add( formataMesBase(data) );

            incremento ++;
        }

        return retorno;

    }

    public String formataMesBase(Date pData) {

        SimpleDateFormat sDF = new SimpleDateFormat("MM/yyyy");

        String data = sDF.format(pData);

        return data;

    }

    // CONVERTERS
    // CONVERSOR PERSONALIZADO PARA SELECTIONBOX DE DATA BASE
    public Converter getdataBaseConverter(){ 
         return dataBaseConverter;
    }

    private Converter dataBaseConverter = new Converter() {

        @Override
        public Object getAsObject(FacesContext fc, UIComponent comp, String pValue) {

            if (pValue == null || pValue.equals("") || pValue.isEmpty()) {
                return null;
            } else {

                return Integer.parseInt(pValue); 
            }

        }


        @Override
        public String getAsString(FacesContext context, UIComponent comp, Object pDataBase) {

            if(pDataBase == null || pDataBase.equals("")) {
                return null;
            } else {

                return String.valueOf(pDataBase);

            }

        }

    }; //fim do converter



}



我希望在单击按钮时文件下载能够正常工作。

必须在de-ManagedBean中通过其get方法生成并返回文件。如果文件生成在get方法之外,则文件下载不起作用。至少在这个版本中