Как включить файл из папки файловой системы внешнего локального диска в 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 будут рассматриваться только как "простой ванильный" 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 с taglibs и EL. В основном, с вашим подходом JSP, ваш файл PDF загроможден <html> а также <body> теги и, следовательно, повреждены и не распознаются как действительный файл PDF. Это, кстати, одна из причин, почему использование скриптлетов является плохой практикой. Именно это полностью сбило вас с толку относительно того, как вещи должны работать. Facelets не поддерживает никакие формы скриптлетов и, следовательно, "автоматически" заставляет вас делать все правильно. В данном конкретном случае это использует обычный класс Java для задания загрузки файла.

Вы должны использовать сервлет вместо этого. Вот начальный пример, предполагая, что 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());
    }

}

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

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

Другие вопросы по тегам