0

我用过 JSF 和 PrimeFaces。我有一个 ActionListener 在有人单击 MenuItem 时触发:

@Override
public void processAction(ActionEvent event) throws AbortProcessingException
{
    Resource resouce = getResources().get(0);
    try
    {
        ResourceDelegate delegate = new ResourceDelegate(resouce, configDao);
        JSFUtils.writeToOutputStream(Mime.getMimeTypeForFileType(FileUtilities.getExtension(resouce.getName())), delegate.getData());
    }
    catch(Exception e)
    {
        logger.log(Level.SEVERE, "Cant show resource",e);
    }

}

在该菜单项中,我使用以下代码将图像数据写入请求流:

/**
 * Writes binary data to the response for the browser to display
 * @param contentType
 * @param data
 * @throws IOException 
 */
public static void writeToOutputStream(String contentType, byte[] data) throws IOException
{
    FacesContext context = FacesContext.getCurrentInstance();
    HttpServletResponse hsr = getHttpServletResponse();
    hsr.setContentType(contentType);
    OutputStream stream = hsr.getOutputStream();
    stream.write(data);
    //Tell JSF to skip the remaining phases of the lifecycle
    context.responseComplete();
}

当 ActionListener 完成后,我希望图像会显示出来,但事实并非如此。什么都没发生。我还需要做些什么才能使图像正确显示吗?

4

1 回答 1

4

如果请求由 ajax 触发,则可能会发生这种情况,几乎所有 PrimeFaces 操作组件默认情况下都是这种情况。在 JSF/PrimeFaces 的情况下,ajax 请求应该返回一个特殊的 XML 响应,其中包含关于 HTML DOM 的哪些部分要更新以及如何更新的信息。

但是,您在这里发送“文件下载”作为 ajax 响应。PrimeFaces 的 ajax 引擎不能这样解释。此外,由于安全原因,JavaScript 没有强制另存为对话的工具。它确实应该由同步请求来请求。

在 PrimeFaces 的情况下<p:menuitem>,您需要添加ajax="false"属性以关闭 ajax 特性并让它触发同步请求。

<p:menuitem ... ajax="false" />

(PrimeFaces 的所有其他动作组件也可以使用相同的属性,例如<p:commandButton>

“什么都没有发生”实际上是不正确的。您会在 webbrowser 的内置 webdeveloper 工具集的“网络”部分看到具体的 HTTP 响应(在 Chrome/IE9/Firebug 中按 F12)。您甚至可能在 JavaScript 控制台中出现关于无法解释的 ajax 响应的 JavaScript 错误。

也可以看看:

于 2012-11-17T17:16:54.090 回答