Загрузка файла во время события p: ajax rowSelect в p: dataTable - PullRequest
0 голосов
/ 09 января 2020

Я хочу скачать файл документа по строкам, щелкнув по элементам данных, доступным для сравнения. Я попытался вызвать действие из Бина, используя ajax, например:

<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>

Но следующий код не выполняет то, что я хочу. Логика c моего действия верна. Но похоже, что загружаемый документ не работает с ajax Запросом. Реакции не происходит, и загрузка не выполняется.

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

Есть ли альтернатива для загрузки файла, нажав на строку данных?

1 Ответ

3 голосов
/ 09 января 2020

Вы не можете загружать файлы с помощью JSF / PrimeFaces Ajax. Вместо этого сделайте запрос не Ajax.

Замените ajax слушатель в <p:ajax> запросом GET в oncomplete что-то вроде:

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

И замените компонент поддержки метод actionDownload() простым ванильным сервлетом что-то вроде:

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

}
...