快速实现 pdf / image 预览

预览 pdf / image

后台要求增加一个 预览pdf和图片文件的功能,查了一下实现方法,网上首推 pdf.js,我瞎捣鼓了一下,很是发现了几种实现方式,都挺便捷的。

  1. 访问静态文件url
  2. 通过文件流
  3. HTML标签+Base64
  4. pdf.js

下面详细说明一下几种方式的特点,并附上代码,由于我是使用的 layui,故例子都是layui的实现,其他框架也是差不多的,核心思路不变。

访问静态文件url

顾名思义,这种方式是针对已有的静态资源,不需要后端将其转换为流。

使用注意事项:

  • 依赖浏览器对图片和pdf的支持,通常浏览器会解析为预览或者下载。
  • 可以被下载监听插件比如IDM监听拦截,如果有相关插件,需要禁用或者添加例外。

示例:

// layui.layer
layer.open({
    title: "预览",
    type: 2, // iframe层,content 为url
    area: ['1000px', '750px'],
    content: '../static/a.pdf'
});

通过文件流

比较适合动态的文件的访问,原理就是服务端将文件读取并写入到输出流中,前端读取流内容。
这种方式比较灵活,对文件没什么限制

使用注意事项:

  • 依赖浏览器的支持,可能会解析成预览或下载,
  • 可以被下载监听插件比如IDM监听拦截。

示例:

// layui.layer
layer.open({
    title: "预览",
    type: 2, // iframe层,content 为url
    area: ['1000px', '750px'],
    content: '${pageContext.request.contextPath }/preview.pdf',
});

Java后端返回流示例:

public void detail(HttpServletRequest request, HttpServletResponse response) {

        // 生成或读取文件到字节数组
        byte[] bytes = xxx;

        // 写入到输出流中
        try {
            response.getOutputStream().write(bytes);
            // 设置文件类型
            response.setContentType("application/pdf;charset=UTF-8");
        } catch (IOException e) {
            log.error("",e);
        }
    }

HTML标签 + Base64

这种情况适用于使用时,已经加载到了客户端的资源。

特点:

  • 开发简单
  • 吃客户端内存
  • 只加载一次,能有效减少网络io,如果文件比较大,还能节省大量时间

示例:

layer.open({
    title: "预览",
    type: 1, // 页面层, content支持文本和html
    area: ['1000px', '750px'],
    // image tag
    content:  '<img src="data:image/png;base64,' + data.base64 + '"/>',
    // pdf tag
    content: '<embed src="data:application/pdf;base64,'+ data.base64 +'" type="application/pdf" width="100%" height="100%">'
});

*pdf.js

网上用这个的人比较多,pdf.js 支持新老版本浏览器,可以基于viewer.html进行修改定制。
由于需求与效率原因,没有尝试,如果以上三板斧不能满足需求,pdf.js应该是不错的。

附: (pdf.js 官方连接)[https://github.com/mozilla/pdf.js]