简体   繁体   中英

Downloading file during p:ajax rowSelect event in p:dataTable

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?

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());
    }

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM