0
votes

I want to download a document file by row click on primefaces datatable. I tried to call the action from Bean by using ajax like this:

<p:dataTable
            id="docId"
            value="#{testBean.document}"
            var="doc"
            selectionMode="single"
            selection="#{testBean.selectedDoc}"
            >

            <p:ajax event="rowSelect" listener="#{testBean.actionDownload}"/>

            <p:column>
                ...
            </p:column>
                ...
</p:dataTable>

But the following code does not execute what I want. The logic of my action is correct. But seems so that the downloading document does not work with ajax Request. There is no reaction and the download does not executed.

public String actionDownload() {
    try {
        FacesContext facesContext = FacesContext.getCurrentInstance();
        HttpServletResponse response = (HttpServletResponse) facesContext.getExternalContext().getResponse();

        StringBuffer contentDisposition = new StringBuffer();
        contentDisposition.append("attachment;");
        contentDisposition.append("filename=\"");
        contentDisposition.append(name);
        contentDisposition.append("\"");

        response.reset();
        response.setContentType("application/x-download");

        response.setHeader("Content-Disposition", contentDisposition.toString());
        ServletOutputStream out = response.getOutputStream();
        response.setContentType("application/x-download");
        out.write(output);
        out.close();
    } catch (IOException e) {
        System.out.println(e.getMessage());
    }
    FacesContext.getCurrentInstance().responseComplete();
    return null;
}

Is there an alternative to download a file by click on Datatable row?

1
Is the method actionDownload() getting invoked?Selaron
@Selaron: from what I get it is not. Remarkable that OP thinks it is related to downloading and not tries to put just a system.out.println in thereKukeltje
@Selaron: Yes, method actionDownload() is invoked and executed. But nothing happened. I tested the method actionDownload() by calling from commandButton and everything was ok. But calling by Ajax does not bring the same result.ivguero
See there you narrowed down the problem. I thought there would be a duplicate (therefor I did not answer yet and wanted you to narrow down the problem) bit if @BalusC answers there is no need to try to find a duplicate since there with 99,999% certainty is notKukeltje

1 Answers

3
votes

You cannot download files with JSF/PrimeFaces Ajax. Make it a non-Ajax request instead.

Replace ajax listener in <p:ajax> by a GET request in oncomplete something like:

<p:ajax event="rowSelect" oncomplete="window.location='#{request.contextPath}/download/#{doc.id}'"/>

And replace backing bean method actionDownload() by a plain vanilla Servlet something like:

@WebServlet("/download/*")
public class Download extends HttpServlet {

    @Inject
    private DocumentService service;

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        Document document = service.find(Long.valueOf(request.getPathInfo().substring(1)));
        response.setContentType(getServletContext().getMimeType(document.getFileName()));
        response.setContentLength(document.getContent().length);
        response.setHeader("Content-Disposition", "attachment;filename=\"" + URLEncoder.encode(document.getFileName(), "UTF-8") + "\"");
        response.getOutputStream().write(document.getContent());
    }

}