【问题标题】:Displaying pdf in jsp在jsp中显示pdf
【发布时间】:2013-04-20 10:04:39
【问题描述】:

我写了一个 jsp 页面来显示 pdf 的内容,但在 jsp 中以 ascii 代码结束。我想在jsp中显示pdf的内容。什么是我错过的部分。当我尝试以 pdf 格式写入读取内容时,它仅显示 ascii 值而不是可读格式

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=${encoding}"></head>

<%@page import="java.io.File"%>
<%@page import="java.io.*"%>
<%@page import="javax.servlet.*"%>
<%@page import="com.itextpdf.text.Image"%>
<%@page import="com.itextpdf.text.Document"%>
<%@page import="com.itextpdf.text.DocumentException"%>
<%@page import="com.itextpdf.text.pdf.PdfReader"%>
<%@page import="com.itextpdf.text.pdf.PdfImportedPage"%>
<%@page import="com.itextpdf.text.pdf.PdfWriter"%>
<%@page import="com.itextpdf.text.pdf.PdfContentByte"%>
<%@ page language="java" contentType="application/pdf; charset=UTF-8"
    pageEncoding="UTF-8"%>

<%
    response.reset();
    response.setContentType("application/pdf");
    File file = new File("D:\\TNWRD_Documents\\CHAPTER_II.pdf");
    response.setHeader("Content-Type", "application/pdf");
    response.setHeader("Content-Disposition",
            "inline;filename=Saba_PhBill.pdf");
    response.setContentLength((int) file.length());
    response.setHeader("Content-Type",
            getServletContext().getMimeType(file.getName()));
    response.setHeader("Content-Length", String.valueOf(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);
            out.write(outs.toString());
        }

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

【问题讨论】:

  • 在您的 JSP 指令之前,您有一个完整的 HTTP 标头。当您的 JSP 代码执行 response.reset(), 时,该标头很可能已经发送。此外,您在发送 PDF 后发送结束 &lt;/html&gt; 标记,这也会使结果成为无效的 PDF。
  • 我的评论比较笼统:引入 JSP 技术是为了消除 HTML 污染 Java 代码的必要性。你用 JSP 编写了一个 servlet,并设法用 HTML 污染了它。
  • 有趣的是,您用[servlets] 标记了这个问题,尽管您根本没有在代码中使用 servlet,但它具体的正确答案问题!基本上,你事先已经知道答案,只是你没有看到。

标签: java jsp servlets pdf


【解决方案1】:

我可以看到多个问题:

  • 在 JSP 的顶部和底部有额外的 html 标记。您不希望它们在那里 - 您只想在响应输出中包含 pdf 内容。
  • 代码集内容类型为多次。这可能不是根本原因,但请确保只执行一次(将其设置为 application/pdf
  • 在while循环中,首先将数据写入响应输出流,然后将toString()写入out(实际上是在响应输出流上打开的Writer实例-outs中的那个)。只在循环中使用响应流,如

    while ((c = in.read(buf, 0, buf.length)) > 0) { outs.write(buf, 0, c);
    }

【讨论】:

    【解决方案2】:

    JSP 是提供文件下载服务的错误工具。 JSP 被设计为一种视图技术,旨在通过标记库和 EL 轻松生成 HTML 输出。基本上,使用您的 JSP 方法,您的 PDF 文件会被 &lt;!DOCTYPE&gt;&lt;html&gt; 等标签弄乱,因此已损坏且无法识别为有效的 PDF 文件。顺便说一句,这是using scriptlets is a bad practice 的原因之一。它让你完全混淆了东西应该如何工作。在这种特殊情况下,即使用普通的 Java 类进行文件下载作业。

    您应该改用servlet。这是一个启动示例,假设 Servlet 3.0 和 Java 7 可用:

    @WebServlet("/foo.pdf")
    public class PdfServlet extends HttpServlet {
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            File file = new File("/absolute/path/to/foo.pdf");
            response.setHeader("Content-Type", getServletContext().getMimeType(file.getName()));
            response.setHeader("Content-Length", String.valueOf(file.length()));
            response.setHeader("Content-Disposition", "inline; filename=\"foo.pdf\"");
            Files.copy(file.toPath(), response.getOutputStream());
        }
    
    }
    

    (如果 Servlet 3.0 不可用,则将其映射到 web.xml the usual way,如果 Java 7 不可用,则使用读/写循环 the usual way

    只需将这个类全部复制粘贴到您的项目中,然后通过/contextpath/Saba_PhBill.pdf而不是/contextpath/youroriginal.jsp打开所需的PDF文件(当然,在将它组织在一个包中并在类中自动完成必要的导入之后)。

    例如在您想要显示 PDF 内联的 JSP 中如下所示:

    <object data="${pageContext.request.contextPath}/Saba_PhBill.pdf" type="application/pdf" width="500" height="300">
        <a href="${pageContext.request.contextPath}/Saba_PhBill.pdf">Download file.pdf</a>
    </object>
    

    (当使用的浏览器不支持在 HTML 文档中内联 application/pdf 内容时,即当它没有安装 Adob​​e Reader 插件时,&lt;a&gt; 链接意味着优雅降级) em>

    另见:

    【讨论】:

    【解决方案3】:

    假设我们完全忽略了反对使用 JSP 的建议(正如 BalusC 所说 - 有更好的方法),这里有一个 丑陋可耻 的小笨蛋,它适用于我。它甚至没有设置所有正确的标题,但这里有:

    <%@ page import="java.io.File" %><%@ page import="org.apache.commons.io.FileUtils" %><%
    File pdfFile = (File) request.getAttribute("pdf");
    byte[] pdfByteArray = FileUtils.readFileToByteArray(pdfFile);
    response.setContentType("application/pdf");
    response.getOutputStream().write(pdfByteArray);
    response.getOutputStream().flush();
    %>
    

    确保在 scriptlet 标记之外没有换行符(或其他空格)很重要。

    他们让我这样做,好吗?!

    【讨论】:

    • 可悲但确实如此,有时您必须以丑陋的方式做事:) Yu 也可以删除 fileUtils 创建,除非您使用“FileUtils.readFileToByteArray”以外的其他方法。无论如何,谢谢你这个蛮力的脚本:)
    • 太好了,谢谢@lbrutti - 我已经删除了多余的代码。很高兴它有帮助!
    猜你喜欢
    • 1970-01-01
    • 2021-08-10
    • 2018-09-12
    • 2012-06-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多