Как включить файл из папки локальной локальной файловой системы локального диска в JSF

Я включил JSP-страницу в Facelets, используя <ui:include>. На странице JSP я могу получить PDF файл, но он отображает содержимое как обычный текст. Как это вызвано и как я могу его решить?

Страница JSP:

<html>
<%@page import="java.io.File"%>
<%@page import="java.io.*"%>
<body>
    <%
        response.reset();
    File file = new File(
            "D:\\TNWRD_Documents\\Knowladge_Base\\Financial_and_Administrative_powers.pdf");
        response.setHeader("Content-Type", "application/pdf");
        response.setHeader("Content-Disposition","inline;filename=Saba_PhBill.pdf");
        response.setContentLength((int)file.length());

        //OPen an input stream to the file and post the file contents thru the
        //servlet output stream to the browser
        FileInputStream in = new FileInputStream(file);
        ServletOutputStream outs = response.getOutputStream();
        response.setContentLength(in.available());
        byte[] buf = new byte[8192];
        int c=0;
        try {
            while ((c = in.read(buf, 0, buf.length)) > 0) 
            {
            //System.out.println("size:"+c);
            outs.write(buf, 0, c);
            }

        } catch (IOException ioe) {
            ioe.printStackTrace(System.out);
        } finally {
            outs.flush();
            outs.close();
            in.close();
        }
    %>
</body>
</html>

Страница Facelets:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
    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:a4j="http://richfaces.org/a4j"
    xmlns:rich="http://richfaces.org/rich"
    xmlns:my="http://example.com/jsf"
    >

    <h:form>
        <table width="100%" border="1">
        <tr></tr>
            <tr>
            <td align="left" width="200px"><rich:tree id="fileTree" toggleType="ajax" var="item">
                <rich:treeModelRecursiveAdaptor
                    roots="#{fileSystemBean.sourceRoots}" nodes="#{item.directories}">
                    <rich:treeNode>
                    #{item.shortPath}
                </rich:treeNode>
                    <rich:treeModelAdaptor nodes="#{item.files}">
                        <rich:treeNode>
                            <a4j:commandLink value="#{item}"
                                action="#{TnwrdAction.downloadFile}" oncomplete="openFile();" render="fileTree"
                                immediate="true">
                                <f:setPropertyActionListener value="#{item}"
                                    target="#{TnwrdBean.fileName}" />

                            </a4j:commandLink>
                        </rich:treeNode>
                    </rich:treeModelAdaptor>
                </rich:treeModelRecursiveAdaptor>
                </rich:tree></td>
            <td >
            <ui:insert name="Barrage" >
            <my:include page="/WEB-INF/jsp/page.jsp" />
            </ui:insert>  
            </td>
            </tr>
            </table>
    </h:form>

</ui:composition>

Ответ 1

В этой конструкции есть как минимум две основные ошибки.

Прежде всего, вы не можете включать JSP файлы, используя <ui:include>. Он может включать только файлы Facelets. Файлы JSP будут обрабатываться только как "plain vanilla" XML. Кроме того, JSP устарел с JSF 2.0. Вы никогда не должны думать об использовании этого. <ui:include> также является неправильным инструментом для встраивания PDF файла в выходной файл. Вместо этого вы должны использовать HTML <iframe> или <object>.

например.

<iframe src="/url/to/file.pdf" width="500" height="300"></iframe>

или, лучше

<object data="/url/to/file.pdf" type="application/pdf" width="500" height="300">
    <a href="/url/to/file.pdf">Download file.pdf</a>
</object>

(ссылка <a> подразумевается как изящное ухудшение, когда используемый браузер не поддерживает вложение содержимого application/pdf в HTML-документ, т.е. когда он не установлен плагин Adobe Reader)

или если вы используете PrimeFaces

<p:media value="/url/to/file.pdf" width="500" height="300" />

Во-вторых, JSP является неправильным инструментом для работы с загрузкой файла. JSP похож на Facelets, разработанный как технология просмотра, с целью легкого создания HTML-вывода с taglib и EL. В основном, с вашим подходом JSP, ваш файл PDF загроможден тегами <html> и <body> и поэтому поврежден и не распознается как действительный файл PDF. Это, кстати, одна из причин, почему использование скриптов является плохой практикой. Это полностью смутило вас в отношении того, как материал должен работать. Facelets не поддерживает любую форму скриптлетов и, следовательно, "автоматически" заставляет вас делать все правильно. В этом конкретном случае используется обычный класс Java для задания загрузки файла.

Вместо этого вы должны использовать servlet. Здесь приведен пример запуска, предполагающий, что Servlet 3.0 и Java 7 доступны:

@WebServlet("/Saba_PhBill.pdf")
public class PdfServlet extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        File file = new File("D:\\TNWRD_Documents\\Knowladge_Base\\Financial_and_Administrative_powers.pdf");
        response.setHeader("Content-Type", getServletContext().getMimeType(file.getName()));
        response.setHeader("Content-Length", String.valueOf(file.length()));
        response.setHeader("Content-Disposition", "inline; filename=\"Saba_PhBill.pdf\"");
        Files.copy(file.toPath(), response.getOutputStream());
    }

}

(у вас, кстати, серьезная опечатка в "Нодадже", не уверен, что это еще более актуально для конкретной проблемы)

Просто замените "/url/to/file.pdf" на "#{request.contextPath}/Saba_PhBill.pdf" в приведенных выше примерах HTML, чтобы вызвать его. В <p:media> #{request.contextPath} не требуется.