如何在JSF 2上提交ajax后生成文件下载流?

时间:2014-11-14 16:10:43

标签: java ajax file jsf phaselistener

在JSF 2和Primefaces中执行按钮操作方法之后,我想生成一个动态XML文件。

  • 如果我在该按钮上启用了ajax,则输出流不会下载到客户端
  • 如果我是aable ajax,输出流是成功下载的,但验证没有按预期执行

动作方法如下所示:

public void someAction() {
    FacesContext context = FacesContext.getCurrentInstance();
    ExternalContext ec = context.getExternalContext();
    try {
        Object someResult = manager.doSomeBusinessLogic();

        String contentType = "application/some-type;charset=utf-8";
        ec.responseReset(); 
        ec.setResponseContentType(contentType);
        ec.setResponseHeader("Content-Disposition", "attachment; filename=\"test.x\""); 

        OutputStream outputStream = ec.getResponseOutputStream();
        writeDataToStream(outputStream, someResult);
    } catch (... ex) {
        log.error("error", ex);
    } finally {
        context.responseComplete();
    }
}

有没有办法在启用Ajax并在请求结束时下载文件的情况下执行此操作?

注意:我还尝试使用PhaseListener来拦截执行,但我不知道如何将参数传递给请求,以便afterPhase能够相应地处理参数 - 而且我会而不是做一些重定向才能进入PhaseListener。有什么想法吗?

编辑:我正在使用Omnifaces 1.6.3和Primefaces 5.1。

这是xhtml:

<o:form>
    <h:inputText id="field" value="#{bean.someField}" />
    <p:commandButton value="Ajax submit button" action="#{bean.someAction}" />
    <f:phaseListener type="com.company.package.SomePhaseListener"/>
</o:form>

这是我在阶段监听器实现中的赠送;唯一的限制是将someParam参数添加到操作方法的HttpServletRequest

public class SomePhaseListener implements PhaseListener {

    @Override
    public PhaseId getPhaseId() { return PhaseId.RENDER_RESPONSE; }

    @Override
    public void beforePhase(PhaseEvent event) { ... }

    @Override
    public void afterPhase(PhaseEvent event) {
        FacesContext context = event.getFacesContext();
        HttpServletRequest request = (HttpServletRequest) context.getExternalContext().getRequest();
        HttpServletResponse response = (HttpServletResponse) context.getExternalContext().getResponse();
        String someResult = request.getParameter("someParam");
        if(someResult != null) {
            try {
                ExternalContext ec = context.getExternalContext();    
                ec.responseReset(); 
                ec.setResponseContentType(contentType);
                ec.setResponseHeader("Content-Disposition", "attachment; filename=\"test.x\""); 

                OutputStream outputStream = response.getOutputStream();
                writeDataToStream(outputStream, someResult);
            } catch (... ex) {
                log.error(null, ex);
            } finally {
                context.responseComplete();
            }
        }
    }
}

0 个答案:

没有答案