在jsp中显示pdf
我写了一个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是服务文件下载工作的错误工具。 JSP被devise为一种视图技术,目的是使用taglibs和EL轻松生成HTML输出。 基本上,用你的JSP方法,你的PDF文件与<!DOCTYPE>
, <html>
etc标签混杂在一起,因此被损坏,不能识别为有效的PDF文件。 这就是为什么使用scriptlet是一个不好的做法的原因之一。 它已经完全混淆了你的东西是如何工作的。 在这种特殊情况下,即使用普通的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
中 ,如果Java 7不可用,那么以通常的方式使用读/写循环)
只需把这个类全部复制到你的项目中,并通过/contextpath/Saba_PhBill.pdf
而不是/contextpath/youroriginal.jsp
打开所需的PDF文件(在将它组织到一个包中并自动完成必要的导入之后)。
例如,如果您想在内部显示PDF,
<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
内容时(即,没有安装Adobe Reader插件时), <a>
链接就意味着优雅的降级)
也可以看看:
- 在Java Web应用程序中从应用程序服务器外部提供静态数据的最简单方法
- 支持ETags,caching等的静态资源servlet的抽象模板
我可以看到多个问题:
- 在JSP的顶部和底部有额外的html标签。 你不想让他们在那里 – 你只想在你的响应输出中有pdf内容。
- 代码集的内容types是多次。 这可能不是根本原因,但是确保只做一次(将其设置为
application/pdf
) -
在while循环中,首先将数据写入响应输出stream,然后将
toString()
写入输出(实际上是在响应输出stream上打开的Writer实例 – 输出中的一个)。 仅在循环中使用响应streamwhile ((c = in.read(buf, 0, buf.length)) > 0) { outs.write(buf, 0, c);
}
假设我们完全忽略了使用JSP的build议(正如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标签之外没有新行(或其他空格)。
他们让我做,好吗?!