Downloading file from IceFaces tree

2019-08-29 12:30发布

问题:

I'm still on the road of learning JSF. I have an IceFaces tree with an IceFaces commandLink to try to download a file. So far this is my xhtml and my backing bean. When I click the commandLink it just prints the two messages and then it does nothing and it does not show any warning any error at all... How to know what's happening? What am I missing?

Cheers

XHTML

<?xml version='1.0' encoding='UTF-8' ?>
<!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:ice="http://www.icesoft.com/icefaces/component">
    <h:head>
        <title>Facelet Title</title>
    </h:head>
    <h:body>
        <h:form>
            <ice:tree id="tree"
                      value="#{treeBean.model}"
                      var="item"
                      hideNavigation="false"
                      hideRootNode="false"
                      imageDir="./images/">
                <ice:treeNode>
                    <f:facet name="icon">
                        <ice:panelGroup style="display: inline">
                            <h:graphicImage value="#{item.userObject.icon}"/>
                        </ice:panelGroup>
                    </f:facet>
                    <f:facet name="content">
                        <ice:panelGroup style="display: inline">
                            <ice:commandLink action="#{treeBean.doDownload(item.userObject.fileAbsolutePath)}">
                                <ice:outputText value="#{item.userObject.text}"/>
                            </ice:commandLink>
                        </ice:panelGroup>
                    </f:facet>
                </ice:treeNode>
            </ice:tree>
        </h:form>
    </h:body>
</html>

BEAN

@ManagedBean
@ViewScoped
public class TreeBean implements Serializable {

    private final DefaultTreeModel model;

    /** Creates a new instance of TreeBean */
    public TreeBean() {

// create root node with its children expanded
        DefaultMutableTreeNode rootTreeNode = new DefaultMutableTreeNode();
        IceUserObject rootObject = new IceUserObject(rootTreeNode);
        rootObject.setText("Root Node");
        rootObject.setExpanded(true);
        rootObject.setBranchContractedIcon("./images/tree_folder_close.gif");
        rootObject.setBranchExpandedIcon("./images/tree_folder_open.gif");
        rootObject.setLeafIcon("./images/tree_document.gif");
        rootTreeNode.setUserObject(rootObject);

        // model is accessed by by the ice:tree component via a getter method
        model = new DefaultTreeModel(rootTreeNode);

        // add some child nodes
        for (int i = 0; i < 3; i++) {
            DefaultMutableTreeNode branchNode = new DefaultMutableTreeNode();
            FileSourceUserObject branchObject = new FileSourceUserObject(branchNode);
            branchObject.setText("SteveJobs.jpg");
            branchObject.setFileAbsolutePath("/Users/BRabbit/Downloads/SteveJobs.jpg");
            branchObject.setBranchContractedIcon("./images/tree_folder_close.gif");
            branchObject.setBranchExpandedIcon("./images/tree_folder_open.gif");
            branchObject.setLeafIcon("./images/tree_document.gif");
            branchObject.setLeaf(true);
            branchNode.setUserObject(branchObject);
            rootTreeNode.add(branchNode);
        }


    }

    public DefaultTreeModel getModel() {
        return model;
    }

    public void doDownload(String fileAbsolutePath) {
        System.out.println(fileAbsolutePath);

        File file = new File(fileAbsolutePath);

        if(file.exists())
            System.out.println("Yes"); //It exists !

        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) {
            Logger.getLogger(TreeBean.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(TreeBean.class.getName()).log(Level.SEVERE, null, ex);
        } finally {
            IOUtils.closeQuietly(output);
            IOUtils.closeQuietly(input);
        }

        facesContext.responseComplete();

    }
}

Bean's object

public class FileSourceUserObject extends IceUserObject{

    String fileAbsolutePath;

    public FileSourceUserObject(DefaultMutableTreeNode wrapper) {
        super(wrapper);
    }

    public String getFileAbsolutePath(){
        return fileAbsolutePath;
    }

    public void setFileAbsolutePath(String fileAbsolutePath){
        this.fileAbsolutePath = fileAbsolutePath;
    }

}

回答1:

Finally I did it! Here's some code that allows the user to see a tree (of Files) and download them.

XHTML

        <ice:tree id="tree"
                  value="#{treeBean.model}"
                  var="item"
                  hideNavigation="false"
                  hideRootNode="false"
                  imageDir="./images/">
            <ice:treeNode>
                <f:facet name="icon">
                    <ice:panelGroup style="display: inline">
                        <h:graphicImage value="#{item.userObject.icon}"/>
                    </ice:panelGroup>
                </f:facet>
                <f:facet name="content">
                    <ice:panelGroup style="display: inline-block">
                        <ice:outputResource resource="#{item.userObject.resource}" 
                                            fileName="#{item.userObject.text}"
                                            shared="false"/>
                    </ice:panelGroup>
                </f:facet>
            </ice:treeNode>
        </ice:tree>

BACKING BEAN

@ManagedBean
@ViewScoped
public class TreeBean implements Serializable {

    private final DefaultTreeModel model;

    public TreeBean() {

        DefaultMutableTreeNode rootTreeNode = new DefaultMutableTreeNode();
        FileSourceUserObject rootObject = new FileSourceUserObject(rootTreeNode);
        rootObject.setText("Root Node");
        rootObject.setExpanded(true);
        rootObject.setBranchContractedIcon("./images/tree_folder_close.gif");
        rootObject.setBranchExpandedIcon("./images/tree_folder_open.gif");
        rootTreeNode.setUserObject(rootObject);

        // model is accessed by by the ice:tree component via a getter method
        model = new DefaultTreeModel(rootTreeNode);
        ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
        // add some child nodes
        for (int i = 0; i < 3; i++) {
            DefaultMutableTreeNode branchNode = new DefaultMutableTreeNode();
            FileSourceUserObject branchObject = new FileSourceUserObject(branchNode);
            branchObject.setText("Test.jpg");
            branchObject.setResource(new SRCResource("/<filePath>/Test.jpg"));
            branchObject.setBranchContractedIcon("./images/tree_folder_close.gif");
            branchObject.setBranchExpandedIcon("./images/tree_folder_open.gif");
            branchObject.setLeafIcon("./images/tree_document.gif");
            branchObject.setLeaf(true);
            branchNode.setUserObject(branchObject);
            rootTreeNode.add(branchNode);
        }


    }

    public DefaultTreeModel getModel() {
        return model;
    }

}

SRCResource

public class SRCResource implements Resource {

    private String fileAbsolutePath;
    private final Date lastModified;

    public SRCResource(String fileAbsolutePath) {
        this.fileAbsolutePath = fileAbsolutePath;
        this.lastModified = new Date();
    }

    @Override
    public String calculateDigest() {
        return "No lo calcularé jamás !!";
    }

    @Override
    public InputStream open() throws IOException {
        return (InputStream)(new FileInputStream(fileAbsolutePath));
    }

    @Override
    public Date lastModified() {
        return lastModified;
    }

    @Override
    public void withOptions(Options optns) throws IOException {
    }

    public String getFileAbsolutePath() {
        return fileAbsolutePath;
    }

    public void setFileAbsolutePath(String fileAbsolutePath) {
        this.fileAbsolutePath = fileAbsolutePath;
    }

}

Web.xml

Add the following

<servlet>
    <servlet-name>Resource Servlet</servlet-name>
    <servlet-class>com.icesoft.faces.webapp.CompatResourceServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>Resource Servlet</servlet-name>
    <url-pattern>/xmlhttp/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
    <servlet-name>Faces Servlet</servlet-name>
    <url-pattern>/icefaces/*</url-pattern>
</servlet-mapping>

And that's it ! Simply adapt the code to your needs ! Cheers !

More info on http://wiki.icefaces.org/display/ICE/Adding+ICEfaces+to+Your+Application