-2

I need help in implementing file download in JSF page. So far I managed to create this:

enter image description here

    <?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"    
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:p="http://primefaces.org/ui">
    <h:head>
        <ui:insert name="header">           
            <ui:include src="header.xhtml"/>         
        </ui:insert>
    </h:head>
    <h:body>
        <h1><img src="resources/css/images/icon.png" alt="DX-57" /> Settings Center</h1>
        <!-- layer for black background of the buttons -->
        <div id="toolbar" style="margin: 0 auto; width:100%; height:30px; position:relative;  background-color:black">
            <!-- Include page Navigation -->
            <ui:insert name="Navigation">           
                <ui:include src="Navigation.xhtml"/>         
            </ui:insert>
        </div>  
        <div id="logodiv" style="position:relative; top:35px; left:0px;"> 
            <h:graphicImage alt="Glassfish"  style="position:relative"  value="resources/images/logo_glassfish_settings.png" />
        </div>
        <div id="main" style="margin: 0 auto; width:1190px; height:700px; position:absolute;  background-color:transparent; top:105px">

            <div id="mainpage" style="margin: 0 auto; width:1190px; height:500px; position:absolute;  background-color:transparent; top:80px">

                <div id="settingsdiv" style="width:350px; height:400px; position:absolute;  background-color:r; top:20px; left:1px">

                    <div id="settingsHashMap" style="width:1050px; height:400px; position:absolute;  background-color:r; top:20px; left:1px">

                        <h:form id="form" >
                            <p:growl id="growl" showDetail="true" sticky="true" />
                            <!-- The sortable data table -->
                            <h:dataTable onmouseover="addOnclickToDatatableRows();" id="dataTable" headerClass="columnHeader" value="#{GlassfishController.dataList}" binding="#{table}" var="item">
                                <!-- Check box -->
                                <h:column>
                                    <f:facet name="header">
                                        <h:selectBooleanCheckbox style="margin-left: 0px;" value="#{GlassfishController.mainSelectAll}" class="checkall" >
                                            <f:ajax listener="#{GlassfishController.selectAll}" render="@form" />
                                        </h:selectBooleanCheckbox>
                                    </f:facet>
                                    <h:selectBooleanCheckbox  onclick="highlight(this)" value="#{GlassfishController.selectedIds[item.filename]}" >
                                        <!-- if the user deselects one row deselect the main checkbox -->
                                        <f:ajax listener="#{GlassfishController.deselectMain}" render="@form" />
                                    </h:selectBooleanCheckbox>
                                    <!-- Click on table code -->  
                                    <h:outputLink id="lnkHidden" onclick="document.getElementById('form:btnHello').click(); return false;" style="text-decoration:none; color:white; background-color:black">
                                    </h:outputLink>
                                </h:column>
                                <!-- Row number -->
                                <h:column>
                                    <f:facet name="header">
                                        <h:outputText value="№" />                                    
                                    </f:facet>
                                    <h:outputText value="#{table.rowIndex + GlassfishController.firstRow + 1}" />
                                </h:column>                                
                                <h:column>
                                    <f:facet name="header">
                                        <h:commandLink value="File Name" actionListener="#{GlassfishController.sort}" style="text-decoration:none; color:white; background-color:black">
                                            <f:attribute name="sortField" value="filename" />
                                            <f:ajax render="@form" />
                                        </h:commandLink>
                                    </f:facet>
                                    <h:outputText value="#{item.filename}" />
                                </h:column>
                                <h:column>
                                    <f:facet name="header">
                                        <h:commandLink value="Size" actionListener="#{GlassfishController.sort}" style="text-decoration:none; color:white; background-color:black">
                                            <f:attribute name="sortField" value="size" />
                                            <f:ajax render="@form" />
                                        </h:commandLink>
                                    </f:facet>
                                    <h:outputText value="#{item.size} bytes" />
                                </h:column>

                            </h:dataTable>

                            <!-- The paging buttons -->
                            <h:commandButton value="first" action="#{GlassfishController.pageFirst}"
                                             disabled="#{GlassfishController.firstRow == 0}" >
                                <f:ajax render="@form" execute="@form"></f:ajax>
                            </h:commandButton>&nbsp;


                            <h:commandButton value="prev" action="#{GlassfishController.pagePrevious}"
                                             disabled="#{GlassfishController.firstRow == 0}" >
                                <f:ajax render="@form" execute="@form"></f:ajax>
                            </h:commandButton>&nbsp;

                            <h:commandButton value="next" action="#{GlassfishController.pageNext}"
                                             disabled="#{GlassfishController.firstRow + GlassfishController.rowsPerPage >= GlassfishController.totalRows}" >
                                <f:ajax render="@form" execute="@form"></f:ajax>
                            </h:commandButton>&nbsp;    

                            <h:commandButton value="last" action="#{GlassfishController.pageLast}"
                                             disabled="#{GlassfishController.firstRow + GlassfishController.rowsPerPage >= GlassfishController.totalRows}" >
                                <f:ajax render="@form" execute="@form"></f:ajax>
                            </h:commandButton>&nbsp;

                            <h:outputText value="Page #{GlassfishController.currentPage} / #{GlassfishController.totalPages}" />
                            <br />

                            <!-- The paging links -->
                            <ui:repeat value="#{GlassfishController.pages}" var="page">
                                <h:commandLink value="#{page}" actionListener="#{GlassfishController.page}"
                                               rendered="#{page != GlassfishController.currentPage}" style="text-decoration:none;color:white;">
                                    <f:ajax render="@form" execute="@form"></f:ajax>   
                                </h:commandLink>
                                <h:outputText value="#{page}" escape="false"
                                              rendered="#{page == GlassfishController.currentPage}" style="text-decoration:none;color:gray;"/>
                            </ui:repeat>
                            <br />

                            <!-- Set rows per page -->
                            <h:outputLabel for="rowsPerPage" value="Rows per page" />
                            <h:inputText id="rowsPerPage" value="#{GlassfishController.rowsPerPage}" size="3" maxlength="3" />
                            <h:commandButton value="Set" action="#{GlassfishController.pageFirst}" >
                                <f:ajax render="@form" execute="@form"></f:ajax>
                            </h:commandButton>&nbsp;
                            <h:message for="rowsPerPage" errorStyle="color: red;" />

                            <!-- hidden button -->
                            <h:commandButton id="deleterow" value="HiddenDelete" action="#{GlassfishController.deleteSelectedIDs}" style="display:none">
                                <f:ajax render="@form"></f:ajax>
                            </h:commandButton>

                            <!-- the delete button -->
                            <h:button value="Delete" onclick="deletedialog(this, 'Do you want to delete the selected rows?'); return false;" />

                            <script type="text/javascript" src="resources/js/tabs.js"></script>


                            <h:commandLink id="btnHello" value="Download Files"  
                                           action="#{GlassfishController.downloadFile}">  
                            </h:commandLink>
                        </h:form>                    
                    </div> 

                </div>                    
            </div>  
        </div>
    </h:body>
</html>


// Execute the download procedure
    public void executeDownload(String filename) throws IOException{
        int DEFAULT_BUFFER_SIZE = 10240;
        String filePath = "/opt/glassfish3/glassfish/domains/domain1/logs/" + filename;

        FacesContext context = FacesContext.getCurrentInstance();
        HttpServletResponse response = (HttpServletResponse) context.getExternalContext().getResponse();
        File file = new File(filePath);
        if (!file.exists())
        {
            response.sendError(HttpServletResponse.SC_NOT_FOUND);
            return;
        }
        response.reset();
        response.setBufferSize(DEFAULT_BUFFER_SIZE);
        response.setContentType("text");
        response.setHeader("Content-Length", String.valueOf(file.length()));
        response.setHeader("Content-Disposition", "attachment;filename=\""
                + file.getName() + "\"");
        BufferedInputStream input = null;
        BufferedOutputStream output = null;
        try
        {
            input = new BufferedInputStream(new FileInputStream(file),
                    DEFAULT_BUFFER_SIZE);
            output = new BufferedOutputStream(response.getOutputStream(),
                    DEFAULT_BUFFER_SIZE);
            byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
            int length;
            while ((length = input.read(buffer)) > 0)
            {
                output.write(buffer, 0, length);
            }
        }
        finally
        {
            input.close();
            output.close();
        }
        context.responseComplete();
    }

There is a problem that I cannot solve and I need help. When I click on the download button I successfully can download the log file. I want to download a file into the JSF table when I click on it. Can you please help me to implement it? Or can you give me some advice how to do it?

Best wishes

user1285928
  • 1,328
  • 29
  • 98
  • 147
  • Do these log files contain tabular data? – Vikdor Aug 24 '12 at 17:22
  • Was this intended to be tagged as JavaScript? – Alex Coleman Aug 24 '12 at 17:23
  • Your buttons inside the `` use ajax, and you can't download a file using ajax. – Luiggi Mendoza Aug 24 '12 at 17:27
  • Also, in your [last question](http://stackoverflow.com/q/12111889/1065197) I posted a link where BalusC (JSF expert) explains how to download a file and add this info: "You only need to make sure that the action method is not called by an ajax request, but that it is called by a normal request as you fire with and . Ajax requests are handled by JavaScript which in turn has due to security reasons no facilities to force a Save As dialogue with the content of the ajax response." – Luiggi Mendoza Aug 24 '12 at 17:30
  • Is there any way to use for example JavaScript to call `action="#{GlassfishController.downLoad}">` in order to download the file? – user1285928 Aug 24 '12 at 17:58
  • I cannot download file into Ajax, but what if I use hidden button and call it with JavaScript? – user1285928 Aug 24 '12 at 18:01
  • Any possible solution in this case? – user1285928 Aug 24 '12 at 19:13
  • Is like you want to link two commandButton/commandLinks, like 1 to prepare the data and the other to download the info? – Luiggi Mendoza Aug 24 '12 at 20:02
  • Yes, I suppose that this can solve the problem? – user1285928 Aug 24 '12 at 20:37
  • @user1285928 when you want to send a message to a person in comments, you must use the `@` symbol (like I did just now) – Luiggi Mendoza Aug 27 '12 at 03:13

1 Answers1

2

Based in your comments, you can use a commandLink/commandButton to call another commandLink/commandButton in the same page. Remember that these components will behave like normal HTML components. Posting a sample of this behavior

<h:form id="frmTest">
    <h:commandLink value="I will call the commandButton below me"
        onclick="document.getElementById('frmTest:btnHello').click(); return false;" />
    <br />
    <h:commandButton id="btnHello" value="I'm the commandButton below the commandLink"
        action="#{bean.someAction}" />
</h:form>

EDIT: Based on your comment on the question, you have several ways to pass the parameter to your commandButton action. I'll show you one that uses JavaScript. The logic is simple:

  • Use an <h:inputHidden> tag component which value will be the name of the file you want to download.
  • Before sending the onclick event, fill this hidden component with the value you need.
  • Let the HTML request continue with its work.
<h:form id="frmTest">
    <h:commandLink id="hidFileName" value="#{bean.fileToDownload}" />
    <h:commandLink value="I will call the commandButton below me"
        onclick="document.getElementById('frmTest:hidFileName').value='#{bean.fileName}'; document.getElementById('frmTest:btnHello').click(); return false;" />
    <br />
    <h:commandButton id="btnHello" value="I'm the commandButton below the commandLink"
        action="#{bean.someAction}" />
</h:form>
Luiggi Mendoza
  • 85,076
  • 16
  • 154
  • 332
  • I updated the code. There is small detail that needs to be added. When I click on row to call the hidden button I need to pass the file name as argument in order to tell the Java code which file to download. Would you show me how to pass file name as argument in your example? – user1285928 Aug 27 '12 at 10:23