动态PDF在线预览

实战动态PDF在线预览及带签名的PDF文件转换

开篇语:

最近工作需要做一个借款合同,公司以前的合同都是通过app端下载,然后通过本地打开pdf文件,而喜欢创新的我,心想着为什么不能在线H5预览,正是这个想法,说干就干,实践过程总是艰难的,折腾了3,4天的时间,熬了两个凌晨3,4点,其中的艰辛、以及各中的曲折、压力只有自己能体会,项目上线后心里想着我要写一篇博文,一是总结一下经验,其次就是和大家分享自己这一路走来的的心得体会,欢迎吐槽!,废话不多说,来点干货!

PDF在线预览实现:

8个实现在线浏览PDF文件的实用插件,笔者选择pdf.js,下面简单介绍8个插件:

PDFObject

PDFobject可以帮助你在页面直接嵌入pdf文件,有时候有些项目需要动态地嵌入PDF文件。PDFObject为此而设计的,他能够快速和容易的嵌入PDF文件,PDFObject使用JavaScript来产生相同的符合标准的 标记,然后插入 到您的HTML元素的选择。您可以填满整个浏览器窗口,或将PDF格式转换成一个或其他块级元素。

pdf.js

和 Google Chrome 使用的源自 Foxit 的闭源 PDF 浏览插件不同,PDF.js 是基于开放的 HTML5 及 JavaScript 技术实现的开源产品

pdf.js 是一个主要用于HTML5 平台上在线阅读PDF文档的小插件,基于JavaScript技术编写而成,无需任何本地技术支持。

pdf.js是由Mozilla Labs发布的。他们的目标是创建一个通用的,基于标准的网络平台,能够解析和渲染PDF文件,并最终发布一个PDF阅读器扩展,毫无疑问 pdf.js 将被整合入 Gecko 成为 Firefox 的内嵌 PDF 阅读器,但是具体整合时间表尚未确定

jsPDF

jsPDF 是一个使用Javascript语言生成PDF的开源库。你可以在Firefox插件,服务端脚本或是浏览器脚本中使用它。客户端Safari 和 iPhone Safari 支持得最好,其次是Opera和Windows下的Firefox 3等。IE暂不支持。。

jQuery Media Plugin

jQuery Media Plugin是一款基于jQuery的网页媒体播放器插件,它支持大部分的网络多媒体播放器和多媒体格式,比如:Flash, Windows Media Player, Real Player, Quicktime, MP3,Silverlight, PDF。它根据当前的脚本配置,自动将a标签替换成div,并生成object, embed甚至是iframe代码,至于生成object还是embed,jQuery Media会根据当前平台自动判别,因此兼容性方面非常出色下面这段代码是jQuery Media生成后的。

Google Docs PDF viewer

ZOHO Viewer

Anychart:使用JavaScript导出PDF

下图可以导出为PNG或JPG格式的静态图像或嵌入式静态图像,图表或一个完全互动的功能图

jQuery Document Viewer

Document Viewer是一个jQuery插件,可以让你在网页中直接查看多种文件格式。文档浏览器支持的文件格式:PDF文件,文本文件,代码,图像,音频,视频等。

PDF.js实践篇

  第一步 pdf.js源码下载https://github.com/mozilla/pdf.js

源码页有详细编译步奏,最后编译出来,将generic文件copy至tomcat webapps目录下,浏览器输入http://localhost:8080/generic/web/viewer.html,H5预览效果如下,图片压缩了,实际预览效果好很多

(我这里覆盖了webapps\generic\web\compressed.tracemonkey-pldi-09.pdf文件,它自带的是英文文档):

  第二步 我集成到项目以插件的形式目录结构如下:

第三步:编写H5文件,这里是将pdf.js viever.html 页面通过Ifram嵌入进来,并通过指定file参数动态传参,实现动态pdf文件预览

loanPdfContract.jsp:

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%><!DOCTYPE html><html><head>    <meta charset="UTF-8"/>    <meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no"/>    <meta name="apple-mobile-web-app-capable" content="yes"/>    <meta name="apple-mobile-web-app-status-bar-style" content="black"/>    <meta name="format-detection" content="telephone=no,email=no,address=no"/>    <title>借款合同</title></head><body>    <iframe src="<c:url value="/plugin/pdfjs/generic/web/viewer.html"/>?file=<c:url value="/app/credit/loanApplication/contracts/${fileId}"/>"            width="100%" height="800">    </iframe></body></html>
第四步:编写Controller方法,
/** * 16.借款申请[信息确认]《合同及相关协议》-借款合同 H5接口 提供给app端调用 * * @param userId * @return * @since 3.4 */@RequestMapping(value ="/app/credit/loanApplication/contracts/loanContract.security")public Object loanContract(String userId,String borrowCode,String productTypeCode, Model model) {   if (StringUtils.isEmpty(userId)  || StringUtils.isEmpty(borrowCode)) {      return "app/credit/canaLoanApplication/404Error";   }   Map<String,String> returnMap = canaApplyLoanService.investmentContractTemplate(userId,borrowCode,productTypeCode);   if( BizCodeType.IS_NO.getCode().equals(returnMap.get("flag"))){      return "app/credit/canaLoanApplication/404Error";   }   model.addAttribute("fileId",returnMap.get("fileId")+".pdf");   return "app/credit/canaLoanApplication/loanPdfContract";}
  第五步:编写Controller方法,注意这个 http head响应头信息设置是HttpStatus.OK,和文件下载HttpStatus.CREATE头信息有差异。

/**

 * 查看PDF文件 * @param fileId * @return * @throws IOException */@RequestMapping(value = "/app/credit/loanApplication/contracts/{fileId}.pdf", method = RequestMethod.GET)public ResponseEntity<byte[]> loadContract(@PathVariable String fileId) throws IOException {   byte[] bytes=canaApplyLoanService.downContract(fileId);   final HttpHeaders headers = new HttpHeaders();   headers.setContentType(MediaType.valueOf("application/pdf"));   headers.setContentLength(bytes.length);   headers.add(HttpHeaders.ACCEPT_RANGES,"bytes");   return new ResponseEntity<byte[]>(bytes, headers, HttpStatus.OK);}

结束语 看着这里,PDF文件在线动态预览基本完成,赶快体验吧!

进阶篇:Java实现PDF文件转图片、多个图片合成PDF文件.

 前言:

    因为笔者这里的PDF文件带有交互式表单域,导致PDF文件无法预览,因为是合同PDF文件,敲章带有签名信息导致PDF预览失败,当时非常迷茫,没有方向,后来和同城金服一架构师朋友聊天中,他给了我提示,“说是签名的问题,需要把PDF转成图片”,对于笔者来说,有了思路剩下的就是实践的事情。

因为PDF有多页所以会转出多张图片,至于为什么要转成图片,仅仅是为了将代签名的交互式表单域给干掉、因为笔者以前做过多张图片合成一张大图,所以当时就想,这个多张图片合成一张PDF文件应该不是问题,对于以前较少玩PDF文件的我来说,这个想法已经非常大胆了,如果读者的你也对PDF文件了解不深的话,那么本文将非常适合你,带你实战PDF!

我在啰嗦一句,因为这个PDF文件签名导致App端无法查看,因为是第三方合同公司,所以我们需要他们的签名SDK文件才能预览,

  第一篇:带你装B,带你飞!

      说了这么多,不来点干货恐怕你们都看不下去了,主流的Pdf与图片互转

1.PDFRenderer: 确实效率最高,但是缺少字体支持对大多数中文pdf处理不了,这个笔者最开始使用了一下,但是报错后来放弃了。

2.jpedal:这个是商业版本的,它官网的jar下载较慢,最开始本来打算用,好不容易csdn down下一个jar包,一运行提示jar包过期了。

3.pdfbox:笔者最终采用pdfbox,效果还不错。之前网上说它对中文支持不好,但是笔者在pdfbox_2.0.2.jar使用过程中都没遇见乱码.

  第二篇:pdfbox使用

   maven配置:

<dependency>   <groupId>org.apache.pdfbox</groupId>   <artifactId>pdfbox</artifactId>   <version>2.0.2</version></dependency>

java代码:

  

import org.apache.pdfbox.pdmodel.PDDocument;import org.apache.pdfbox.pdmodel.PDPage;import org.apache.pdfbox.pdmodel.PDPageContentStream;import org.apache.pdfbox.pdmodel.common.PDRectangle;import org.apache.pdfbox.pdmodel.graphics.image.JPEGFactory;import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;import org.apache.pdfbox.rendering.PDFRenderer;

import javax.imageio.ImageIO;import java.awt.*;import java.awt.geom.AffineTransform;import java.awt.image.BufferedImage;import java.awt.image.ColorModel;import java.awt.image.WritableRaster;import java.io.*;import java.util.ArrayList;import java.util.List;

public class PdfBoxUtil {

    public static void main(String[] args) {        //pdfToImg("D:\\test\\22222.pdf","D:\\test\\22222.PNG");         pdfToImgToPdf("D:\\test\\22222.pdf","D:\\test\\3333.pdf");    }

    /**     * pdf转图片     * @param pdfPath     * @param pngPath     */    public static void pdfToImg(String pdfPath,String pngPath){        //将pdf装图片 并且自定义图片得格式大小        File file = new File(pdfPath);        try {            PDDocument doc = PDDocument.load(file);            PDFRenderer renderer = new PDFRenderer(doc);            int pageCount = doc.getNumberOfPages();            for (int i = 0; i < pageCount; i++) {                BufferedImage image = renderer.renderImageWithDPI(i, 240);                BufferedImage srcImage = resize(image, image.getWidth(), image.getHeight());                ImageIO.write(srcImage, "PNG", new File(pngPath.replace(".",i+".")));            }        } catch (IOException e) {            e.printStackTrace();        }    }    /**     * pdf转图片然后合成pdf     * @param pdfPath     * @param pdfOutPath     */    public static void pdfToImgToPdf(String pdfPath,String pdfOutPath){        //将pdf装图片 并且自定义图片得格式大小        File file = new File(pdfPath);        try {            PDDocument doc = PDDocument.load(file);            PDFRenderer renderer = new PDFRenderer(doc);            int pageCount = doc.getNumberOfPages();            List<BufferedImage> images=new ArrayList<BufferedImage>();            for (int i = 0; i < pageCount; i++) {                BufferedImage image = renderer.renderImageWithDPI(i, 240);                BufferedImage srcImage = resize(image, image.getWidth(), image.getHeight());                images.add(srcImage);            }            //合成图片转pdf            createPDFFromImage(pdfOutPath,images);        } catch (IOException e) {            e.printStackTrace();        }    }    /**     * pdf转图片然后合成pdf     * @param input     */    public static byte[] pdfToImgToPdf(byte[] input){        //将pdf装图片 并且自定义图片得格式大小        byte[] bytes=null;        PDDocument doc=null;        try {            doc = PDDocument.load(input);            List<BufferedImage> images=new ArrayList<BufferedImage>();            PDFRenderer renderer = new PDFRenderer(doc);            int pageCount = doc.getNumberOfPages();            for (int i = 0; i < pageCount; i++) {                BufferedImage image = renderer.renderImageWithDPI(i, 240);                BufferedImage srcImage = resize(image, image.getWidth(), image.getHeight());                images.add(srcImage);            }            bytes=createPDFFromImage(images);        } catch (IOException e) {            e.printStackTrace();        }        if(doc!=null){            try {                doc.close();            } catch (IOException e) {                e.printStackTrace();            }        }        return bytes;    }    /**     *图片合成pdf     * @param images     * @throws Exception     */    public static void createPDFFromImage(String pdfOutPath,List<BufferedImage> images){        PDDocument doc = new PDDocument();        try {            PDPageContentStream contentStream;            PDPage page;            for (BufferedImage image : images) {                page = new PDPage(new PDRectangle(image.getWidth(),image.getHeight()));                doc.addPage(page);                contentStream = new PDPageContentStream(doc,page,PDPageContentStream.AppendMode.APPEND, true);                PDImageXObject pdImageXObject = JPEGFactory.createFromImage(doc,image);                contentStream.drawXObject(pdImageXObject, 0, 0, image.getWidth(),image.getHeight());                contentStream.close();            }            doc.save(pdfOutPath);        }catch (Exception ex){            ex.printStackTrace();        }finally {            if (doc != null) {                try {                    doc.close();                } catch (IOException e) {                    e.printStackTrace();                }            }        }    }    /**     *图片合成pdf     * @param images     * @throws Exception     */    public static byte[] createPDFFromImage(List<BufferedImage> images){        byte[] bytes=null;        ByteArrayOutputStream baos=null;        PDDocument doc = new PDDocument();        try {            PDPageContentStream contentStream;            PDPage page;            for (BufferedImage image : images) {                page = new PDPage(new PDRectangle(image.getWidth(),image.getHeight()));                doc.addPage(page);                contentStream = new PDPageContentStream(doc,page,PDPageContentStream.AppendMode.APPEND, true);                PDImageXObject pdImageXObject = JPEGFactory.createFromImage(doc,image);                contentStream.drawXObject(pdImageXObject, 0, 0, image.getWidth(),image.getHeight());                contentStream.close();            }            baos = new ByteArrayOutputStream();            doc.save(baos);            bytes=baos.toByteArray();        }catch (Exception ex){            ex.printStackTrace();        }finally {            if (baos != null) {                try {                    baos.close();                } catch (IOException e) {                    e.printStackTrace();                }            }            if (doc != null) {                try {                    doc.close();                } catch (IOException e) {                    e.printStackTrace();                }            }        }        return bytes;    }    /**     * 生成图片     * @param source     * @param targetW     * @param targetH     * @return     */    private static BufferedImage resize(BufferedImage source, int targetW, int targetH) {        int type = source.getType();        BufferedImage target = null;        double sx = (double) targetW / source.getWidth();        double sy = (double) targetH / source.getHeight();        if (sx > sy) {            sx = sy;            targetW = (int) (sx * source.getWidth());        } else {            sy = sx;            targetH = (int) (sy * source.getHeight());        }        if (type == BufferedImage.TYPE_CUSTOM) {            ColorModel cm = source.getColorModel();            WritableRaster raster = cm.createCompatibleWritableRaster(targetW, targetH);            boolean alphaPremultiplied = cm.isAlphaPremultiplied();            target = new BufferedImage(cm, raster, alphaPremultiplied, null);        } else {            target = new BufferedImage(targetW, targetH, type);        }        Graphics2D g = target.createGraphics();        g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);        g.drawRenderedImage(source, AffineTransform.getScaleInstance(sx, sy));        g.dispose();        return target;    }

}

总结语:

  到这里笔者得和你说拜拜了,基本上将我三天研究的全部成果贡献,其中一路艰辛,扛过多少坑,你未必知道,我只能告诉你,大多时候我内心是奔溃的!

备注 pdf.js 我项目中的插件源码可至我百度云提取  链接: http://pan.baidu.com/s/1c2JVe1M 密码: k9sc

     要是你在使用过程中遇到问题,可以给我邮件,[email protected]

时间: 2024-10-12 21:22:19

动态PDF在线预览的相关文章

实战动态PDF在线预览及带签名的PDF文件转换

开篇语: 最近工作需要做一个借款合同,公司以前的合同都是通过app端下载,然后通过本地打开pdf文件,而喜欢创新的我,心想着为什么不能在线H5预览,正是这个想法,说干就干,实践过程总是艰难的,折腾了3,4天的时间,熬了两个凌晨3,4点,其中的艰辛.以及各中的曲折.压力只有自己能体会,项目上线后心里想着我要写一篇博文,一是总结一下经验,其次就是和大家分享自己这一路走来的的心得体会,欢迎吐槽!,废话不多说,来点干货! PDF在线预览实现: 8个实现在线浏览PDF文件的实用插件,笔者选择pdf.js,

[Asp.net]常见word,excel,ppt,pdf在线预览方案(转)

引言 之前项目需要,查找了office文档在线预览的解决方案,顺便记录一下,方便以后查询. 方案一 直接在浏览器中打开Office文档在页面上的链接.会弹出如下窗口: 优点:主流浏览器都支持. 缺点:Office文档链接在浏览器中打开,会有如上图的提示,需用户自己选择打开或者保存功能,如果客户电脑上安装迅雷下载软件,会启动迅雷下载,用户体验不好. 方案二 office文档转html,首先引入com组件中office库,然后在程序集扩展中引入word,excel,ppt的dll. 然后F6生成,会

Office在线预览及PDF在线预览的实现方式大集合

一.服务器先转换为PDF,再转换为SWF,最后通过网页加载Flash预览 微软方:利用Office2007以上版本的一个PDF插件SaveAsPDFandXPS.exe可以导出PDF文件,然后再利用免费的swftools.exe工具生成swf格式的Flash文件,网页中加载flexpaper免费开源工具(有广告)实现Flash文件的预览.优点:1.有效的保护的源文件及文件的复制,不可复制也是缺点.2.源码是自己的,版权有保证.缺点:1.服务器上必须安装Office软件.2.导出PDF文件本身是个

[Asp.net]常见word,excel,ppt,pdf在线预览方案

在线预览PDF格式 文章地址:http://www.cnblogs.com/wolf-sun/p/3525437.html [Asp.net]常见word,excel,ppt,pdf在线预览方案 http://www.cnblogs.com/wolf-sun/p/3569960.html http://www.cnblogs.com/wolf-sun/p/3574278.html [Asp.net]常见word,excel,ppt,pdf在线预览方案

Office在线预览及PDF在线预览的实现方式史上最全大集合

Office在线预览及PDF在线预览的实现方式大集合 一.服务器先转换为PDF,再转换为SWF,最后通过网页加载Flash预览 微软方:利用Office2007以上版本的一个PDF插件SaveAsPDFandXPS.exe可以导出PDF文件,然后再利用免费的swftools.exe工具生成swf格式的Flash文件,网页中加载flexpaper免费开源工具(有广告)实现Flash文件的预览.优点:1.有效的保护的源文件及文件的复制,不可复制也是缺点.2.源码是自己的,版权有保证.缺点:1.服务器

Aspose office (Excel,Word,PPT),PDF 在线预览

就是做个备份,拿的是试用版的 Aspose         /// <summary>         /// Aspose office (Excel,Word,PPT),PDF 在线预览         /// </summary>         /// <param name="sourceDoc">需要预览的文件地址</param>         /// <param name="saveDoc"&g

java实现word转pdf在线预览(前端使用PDF.js;后端使用openoffice、aspose)

背景 之前一直是用户点击下载word文件到本地,然后使用office或者wps打开.需求优化,要实现可以直接在线预览,无需下载到本地然后再打开. 随后开始上网找资料,网上资料一大堆,方案也各有不同,大概有这么几种方案: 1.word转html然后转pdf 2.Openoffice + swftools + Flexmapper + jodconverter 3.kkFileView 分析之后最后决定使用Openoffice+PDF.js方式实现 环境搭建 1.安装Openoffice,下载地址:

实现在线预览PDF的几种解决方案

原文:实现在线预览PDF的几种解决方案 因客户需要实现PDF的预览处理,在网上找了一些PDF在线预览的解决方案,有的用PDFJS的在线预览方式,有的使用PDFObject的嵌入式显示,有的通过转换JPG/PNG方式实现间接显示的方式,开始是想通过简单的方式,能够使用JS插件实现预览最好,可是在线预览总是有一些不足,如不同浏览器的兼容问题,甚至不同的手机平台中展示的效果也不一样,不过最好还是采用了间接的方式,把PDF转换为图片展示效果,达到客户的要求. 1.在线实现预览的方式 一开始我还是很倾向使

python爬虫处理在线预览的pdf文档

引言 最近在爬一个网站,然后爬到详情页的时候发现,目标内容是用pdf在线预览的 比如如下网站: https://camelot-py.readthedocs.io/en/master/_static/pdf/foo.pdf 根据我的分析发现,这样的在线预览pdf的采用了pdfjs加载预览,用爬虫的方法根本无法直接拿到pdf内的内容的,对的,你注意到了我说的[根本无法直接拿到]中的直接两个字,确实直接无法拿到,怎么办呢?只能把pdf先下载到本地,然后用工具转了,经过我查阅大量的相关资料发现,工具还