通过 Servlet 显示 Pdf 文档

Posted

技术标签:

【中文标题】通过 Servlet 显示 Pdf 文档【英文标题】:Displaying Pdf Document by Servlet 【发布时间】:2013-12-16 08:41:04 【问题描述】:

我正在尝试在iframe中显示pdf文档。我已将 iframe 的源设置为 servlet,并将一些参数传递给 servlet。

public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException 
    try 
        String docName = request.getParameter("docName");
        String id = request.getParameter("id");

        if (StringUtils.isNotBlank(id) && StringUtils.isNotBlank(docName)) 
            DocumentService service = DamServiceProvider.PROVIDER.getDocumentService();
            FileInBean fileInBean = new FileInBean();
            fileInBean.setDocName(docName);
            fileInBean.setId(Integer.valueOf(id));
            FileDataBean fileDataBean = service.getFileDataBean(fileInBean);

            if (fileDataBean.getStatusCode() == 0) 
                Map<String, String> headerFieldMap = fileDataBean.getHeaderFieldMap();
                String contentType = headerFieldMap.get("Content-type");
                String contentLength = headerFieldMap.get("Content-Length");
                String contentDisposition = headerFieldMap.get("Content-Disposition");

                byte[] stream = fileDataBean.getStream();
                ByteArrayInputStream inputStream = new ByteArrayInputStream(stream);
                OutputStream outputStream = response.getOutputStream();

                response.reset();
                response.setBufferSize(4096);
                response.setContentLength(Integer.valueOf(contentLength));
                response.setContentType(contentType);
                response.setHeader("Content-Disposition", contentDisposition);

                System.out.println(contentDisposition);
                IOUtils.copy(inputStream, outputStream);

                outputStream.close();
                inputStream.close();
            
        
     catch (Exception ex) 
        Log.error(this, ex.getMessage());
    

现在在我的页面中我有一个主细节接口。母版部分包含一系列 pdf 文件项的轮播。单击该项目时,我正在刷新包含 iframe 的详细视图。

我可以看到 servlet 被调用。大多数情况下,iframe 显示的是 pdf 文档。但有时它会显示奇怪的 xml 结构,其中包含 xml 标签和一些不可读的输出。请看附件图片:

这不是特定文件的情况。如果文件显示此输出,则稍后如果单击该项目,它会显示有效的 pdf,如果某个项目稍后显示有效的 pdf,如果我单击它会显示这种输出。当 iframe 显示这种类型的输出时,我的浏览器会显示此 pdf 文档可能已损坏的信息。

我检查了文件所在的存储库,没有发现任何问题。它们都是有效的pdf,我可以通过pdf阅读器下载和打开它们。

我无法找到这个问题的原因。任何指针都会很有帮助。

更新 - 1

我已经检查了输出。它以%% eof结尾,开始时有%pdf。

更新 - 2

我在 Chrome 的网络控制台中检查了 GET 主要返回三种类型的内容类型:application/pdf、text/plain、application/octet-stream。

应用程序/ pdf :它显示pdf。 text/plain 它正在显示我上面提到的内容。 application/octet-stream 没有出现在 Firefox 中,而是出现在 Chrome 中,在这种情况下,它正在打开下载文件窗口。

我在 servlet 中放置了一个日志,以查看从服务返回的内容类型。对于所有情况,它都是 application/pdf

【问题讨论】:

【参考方案1】:

我认为这可能是 content-Type 的问题,您可以使用开发人员工具(在 Chrome 的网络控制台中)确认您的浏览器中是否存在此问题。

【讨论】:

你好。我按照您所说的做了,发现在 chrome 中 GET 正在重新处理三种类型的内容类型:application/pdf、text/plain、application/octet-stream。如果是应用程序/pdf,它会显示 pdf。在 text/plain 的情况下,它显示我上面提到的内容。案例 application/octet-stream 没有出现在 Firefox 中,而是出现在 chrome 中,在这种情况下,它正在打开下载文件窗口。我在 servlet 中放置了一个日志,以查看从服务返回的内容类型。所有案例都是应用程序/pdf。你有什么想法吗? 我不确定,只是一个想法,但您可以查看 Content-Disposition 吗?该值必须是附件或内联(我认为您更喜欢内联)并且必须包含文件名(` httpResponse.setHeader("Content-Disposition", "\"" + getContentDisposition() + "\"" + "; filename= \"" + getFileName() + "\"")); `)。 内容配置没问题。我已经检查过了。【参考方案2】:

试试这样的。

File pdfFile = new File(this.pdfStoreLocation + pdfFileName);
response.setContentType("application/pdf");
response.setHeader("Content-Disposition", "attachment; filename=" + pdfFileName);
response.setContentLength((int) pdfFile.length());

BufferedInputStream bis = new BufferedInputStream(new FileInputStream(pdfFile));
BufferedOutputStream bos = new BufferedOutputStream(response.getOutputStream());

// byte array declared
byte[] buf = new byte[2048];
boolean eof = false;
while (!eof) 
    int length = bis.read(buf);
    if (length == -1) 
        eof = true;
    else 
        bos.write(buf, 0, length);
    


try 
     bis.close();
catch (IOException ex) 
     LOGGER.error("Exception in closing buffered input stream on pdf file->" +   this.pdfStoreLocation + pdfFileName);


try 
     bos.flush();
catch (IOException ex) 
     LOGGER.error("Exception in fliushing buffered output stream on pdf file->"
                            + this.pdfStoreLocation + pdfFileName);

bos.close();

【讨论】:

对不起我的朋友我不能这样做。我没有任何文件。我拥有的是字节数组。如果我使用 IOUtils.copy 方法,你的代码 sn-p 复制两个流是相同的。 是一样的。无论您是从文件还是流创建字节数组都是肤浅的。这个想法是您需要在开始流式传输内容之前添加内容类型标题和处置。这个想法是为了展示它是如何做到的。

以上是关于通过 Servlet 显示 Pdf 文档的主要内容,如果未能解决你的问题,请参考以下文章

为啥不在 java servlet 中创建 pdf 文档? [复制]

servle学习

转载 Servlet3.0中使用注解配置Servle

Servlet基础

如何在 HTML 页面中嵌入 PDF?

java.lang.ClassCastException: cn.itcase.serviceImpl.servicestudentImpl cannot be cast to javax.servl