通过servlet将pdf流式传输到浏览器

3
我有一个典型的servlet,用于向浏览器流传pdf。这些pdf存储在内部服务器上,我的servlet从中提取。如果我直接从浏览器访问servlet,则会显示pdf。如果我尝试在网页中的标签中使用相同的URL,...就会出现断开连接的情况。
有什么见解吗?
作为一项实验,我可以毫无问题地流传gif。
以下是我从网络上搜集来的代码:
public class PdfServlet extends HttpServlet {

    private static final Logger log = Logger.getLogger(PdfServlet.class.getName());

    @Override
    public void doGet(HttpServletRequest req, HttpServletResponse res) {

        String url = (String) req.getParameter("url");

        log.info("The URL is " + url);
        String format = "application/pdf";
//           String format = "image/gif";

        streamBinaryData(url, format, res);

    }

    /*
     * This Method Handles streaming Binary data
     * <p>
     * @param String urlstr ex: http;//localhost/test.pdf etc.
     * @param String format ex: pdf or audio_wav or msdocuments etc.
     * @param ServletOutputStream outstr
     * @param HttpServletResponse resp
     */
    private void streamBinaryData(
            String urlstr,
            String format,
            HttpServletResponse resp) {

        ServletOutputStream outstr = null;
        String ErrorStr = null;

        try {
            outstr = resp.getOutputStream();

            //find the right MIME type and set it as contenttype
            resp.setContentType(format);
            BufferedInputStream bis = null;
            BufferedOutputStream bos = null;
            try {
                URL url = new URL(urlstr);
                URLConnection urlc = url.openConnection();
                int length = urlc.getContentLength();

                resp.setContentLength(length);
//                resp.setHeader("Content-Length", String.valueOf(+length));
//                resp.setHeader("Content-Disposition", "inline");

                // Use Buffered Stream for reading/writing.
                InputStream in = urlc.getInputStream();
                bis = new BufferedInputStream(in);
                bos = new BufferedOutputStream(outstr);
                byte[] buff = new byte[length];
                int bytesRead;
                // Simple read/write loop.
                while (-1 != (bytesRead = bis.read(buff, 0, buff.length))) {
                    log.info("Got a chunk of " + bytesRead);
                    bos.write(buff, 0, bytesRead);
                }
            } catch (Exception e) {
                e.printStackTrace();
                ErrorStr = "Error Streaming the Data";
                outstr.print(ErrorStr);
            } finally {
                log.info("finally!!!");
                if (bis != null) {
                    bis.close();
                }
                if (bos != null) {
                    bos.close();
                }
                if (outstr != null) {
                    outstr.flush();
                    outstr.close();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

...和HTML文件一起,PDF文件出现了“broken pipe”错误,而GIF图像则显示出来,尽管返回的内容类型为“application/pdf”。

<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Cheesy Servlet Experiment</title>
    </head>
    <body>
        <h1>Cheesy Servlet Experiment</h1>

        <P>
            <img src="http://10.0.0.9/ServletExperiment/pdf?url=http%3a%2f%2fwww.samplepdf.com%2fsample.pdf" alt="yah mon">
        <P>
            <img src="http://10.0.0.9/ServletExperiment/pdf?url=http%3a%2f%2fbbs.homeshopmachinist.net%2fimages%2fstatusicon%2fforum_new.gif" alt="yah mon">
    </body>
</html>

编辑 - 以下内容适用于火狐浏览器。我不知道它有多标准。

<object data="http://www.samplepdf.com/sample.pdf" type="application/pdf" width="600" height="600">
    alt : <a href="http://www.samplepdf.com/sample.pdf">test.pdf</a>
</object>

这里有有趣的信息。看起来受到了相当好的支持。


编辑帖子中可能的解决方案。 - Tony Ennis
功能需求是什么?内联显示PDF文件?使用<object>或<iframe>是正常的方法。 - BalusC
目前我认为要求是让“某些东西”工作,哈哈。 PDF文件的服务器在我们的防火墙后面。 在测试时,测试人员显然仍在VPN上或者有一个缓存页面。 我们不知道。 但我们的任何客户都无法查看其PDF文件,并且情况很紧张。 我们在周六推向生产环境。 - Tony Ennis
4个回答

4

您的浏览器是否可以在元素中显示PDF文件?这非常不可能。我认为当浏览器发现它实际上不是图像时,会断开连接。

有些浏览器不会抱怨内容类型。他们检查图像文件并自行确定图像所在的格式。这可以解释为什么您的GIF图像被显示出来。


我从未想过那个。 - Tony Ennis

3
问题在于您试图使用img标签显示PDF文档。 img只能处理像JPEG、GIF或PNG这样的简单图像格式。
通常,普通浏览器无法自行显示PDF内容。如果没有安装PDF查看器插件,那么浏览器将仅显示一个保存对话框以下载PDF文件。
因此,最安全的方法是您的HTML页面仅包含指向PDF文件的链接。也许带有target="_blank"以打开新的浏览器窗口。

1

如果必须使用图像,请使用锚标记将IMG包装在指向真实图像的IMG src中。锚点的href将是显示PDF的servlet。确保在servlet中设置正确的内容类型。


0

首先:你正在尝试一次读取 length

这不是一个好的做法,因为它不能保证任务的完成。

尝试通过 byte [] read_buffer = new byte[1024 * 10] 来读取更小的块,这样你每次读取10kb。

然后将这些10kb写入 bos

read 函数返回 -1 前保持循环。

对了。你不应该用img标签来显示PDF文件。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接