从primefaces树下载文件

时间:2011-12-21 23:11:56

标签: jsf tree download primefaces

这是我的xhtml-code

        <p:tree value="#{documentsController.root}"
                var="node" selectionMode="single"
                dynamic="true">

            <p:treeNode 
                expandedIcon="ui-icon-folder-open"
                collapsedIcon="ui-icon-folder-collapsed">
                <h:outputText value="#{node}" />
            </p:treeNode>

            <p:treeNode type="file" icon="ui-icon-document">
                <h:outputText value="#{node}"/>
            </p:treeNode>

            <p:ajax event="select" listener="#{documentsController.onNodeSelect}"/>

        </p:tree>

这是支持bean

@ManagedBean
@ViewScoped
public class DocumentsController implements Serializable {

    TreeNode root;
    //TreeNode[] selectedNodes;

    @PostConstruct
    public void init() {

        root = new DefaultTreeNode("SRC", null);

        TreeNode node0 = new DefaultTreeNode("A", root);
        TreeNode node1 = new DefaultTreeNode("B", root);
        TreeNode node2 = new DefaultTreeNode("C", root);

        TreeNode node3 = new DefaultTreeNode("file", "D", node0);
        TreeNode node4 = new DefaultTreeNode("file", "E", node0);
        TreeNode node5 = new DefaultTreeNode("file", "F", node0);

        String p = "C:\\Users\\federico.martinez\\Desktop\\a.wmv";

        TreeNode node6 = new DefaultTreeNode("file", new File(p), node1);
        TreeNode node7 = new DefaultTreeNode("file", "h", node1);
        TreeNode node8 = new DefaultTreeNode("file", "i", node1);

    }

    public TreeNode getRoot() {
        return root;
    }

    /*
    public void setSelectedNodes(TreeNode[] selectedNodes){
    this.selectedNodes = selectedNodes;
    }

    public TreeNode[] getSelectedNodes(){
    return selectedNodes;
    }*/
    public void onNodeSelect(NodeSelectEvent event) {
        if (event.getTreeNode().getType().equals("file")) {
            File file = new File(event.getTreeNode().getData().toString());
            FacesContext facesContext = FacesContext.getCurrentInstance();
            ExternalContext externalContext = facesContext.getExternalContext();

            externalContext.setResponseHeader("Content-Type", externalContext.getMimeType(file.getName()));
            externalContext.setResponseHeader("Content-Length", String.valueOf(file.length()));
            externalContext.setResponseHeader("Content-Disposition", "attachment;filename=\"" + file.getName() + "\"");

            InputStream input = null;
            OutputStream output = null;

            try {
                input = new FileInputStream(file);
                output = externalContext.getResponseOutputStream();
                IOUtils.copy(input, output);
            } catch (FileNotFoundException ex) {
                System.out.println("FileNotFound: " + ex.getMessage());
            } catch (IOException ex) {
                System.out.println("IO: " + ex.getMessage());
            } finally {
                IOUtils.closeQuietly(output);
                IOUtils.closeQuietly(input);
            }
            facesContext.responseComplete();
        }
    }
}

但是它没有下载文件,我在Tomahawk树上使用了这个下载方法并且它有效,现在我正在尝试使用PrimeFaces,但这不会下载文件而且没有错误!

任何建议可能出错的地方?

提前致谢!

更新

我有这个修改但无法下载文件。

        <p:tree value="#{documentsController.root}"
                var="node" selectionMode="single"
                dynamic="true">

            <p:treeNode 
                expandedIcon="ui-icon-folder-open"
                collapsedIcon="ui-icon-folder-collapsed">
                <h:outputText value="#{node}" />
            </p:treeNode>

            <p:treeNode type="file" icon="ui-icon-document">
                <p:commandButton value="#{node}" ajax="false">
                    <p:fileDownload value="#{documentsController.download(node)}" />
                </p:commandButton>
            </p:treeNode>

        </p:tree>

和backbean是

public void download(String path) {

    File f = new File(path);
    FacesContext facesContext = FacesContext.getCurrentInstance();
    ExternalContext externalContext = facesContext.getExternalContext();

    InputStream is = ((ServletContext)externalContext.getContext()).getResourceAsStream(path);

    file = new DefaultStreamedContent(is, externalContext.getMimeType(f.getName()), f.getName());   

}

public StreamedContent getFile(){
    return file;
}

1 个答案:

答案 0 :(得分:2)

您的第一个问题是您尝试通过Ajax请求下载文件。这是不可能的。 Ajax由JavaScript代码执行和管理。 JavaScript由于安全限制而无法触发另存为对话。您需要启动一个完整的同步请求。如果内容处置设置为attachment,原始页面将保持不变。

因此,您至少需要<h:commandButton><p:commandButton ajax="false">

您尝试使用<p:fileDownload>时遇到的第二个问题是value必须指向返回StreamedContent而不是void的方法。你已将它绑定到void方法,因此不会返回任何内容。

因此,您需要在StreamedContent值上返回<p:fileDownload>

你的第三个问题是你正在通过ServletContext#getResourceAsStream()将文件作为类路径资源获取(我相信你会盲目地从PrimeFaces展示的例子中进行复制,而这本身也很差,它可能只是用过ExternalContext#getResourceAsStream()而不需要从JSF的引擎盖下抓取ServletContext,但除此之外,而不是原始代码中的FileInputStream

因此,这些解决方案中的任何一个都必须提供帮助:

<p:treeNode type="file" icon="ui-icon-document">
    <p:commandButton value="#{node}" ajax="false">
        <p:fileDownload value="#{documentsController.download(node)}" />
    </p:commandButton>
</p:treeNode>

public StreamedContent download(String path) {
    File file = new File(path);
    InputStream input = new FileInputStream(file);
    ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
    return new DefaultStreamedContent(input, externalContext.getMimeType(file.getName()), file.getName());   
}

<p:treeNode type="file" icon="ui-icon-document">
    <h:commandButton value="#{node}" action="#{documentsController.download(node)}" />
</p:treeNode>

使用原始onNodeSelect()方法,参数更改为String path