2019独角兽企业重金招聘Python工程师标准>>>
前言:
我们知道,Android系统本身不具备打开PDF文件的能力,因此在Android 要实现 PDF 阅读功能需要借助于第三方工具,一般而言有以下方案:
- 使用GoogleDocs提供的在线PDF阅读功能
- 使用第三方应用阅读本地PDF文件
- 使用PDFBox读取编辑PDF文件内容
- 集成第三方SDK,实现本地阅读
- 集成Mozilla的PDF.js,在 WebView 中阅读PDF文件
- 使用 pdf2htmlEX 将PDF 文件转换成 HTML 或者图片
一. 使用GoogleDocs提供的在线PDF阅读功能
GoogleDocs 提供了多种文本格式的阅读能力,我们只需通过 Android 的 WebView 即可实现打开在线 PDF 文档,代码如下所示:
public void setDocumentPath(final String path) {
WebView webView = (WebView) findViewById(R.id.webview);
webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setPluginsEnabled(true);
webView.loadUrl("https://docs.google.com/viewer?url=http://10.200.180.50/dilan/carfree/downLoad/test.pdf");
}
然而这种方案的缺陷同样明显:
- 不支持阅读本地PDF文件;
- 国内通常情况下访问不了 Google 提供 的服务。
二. 使用第三方应用阅读本地PDF文件
用户手机中或多或少会装有一些带有PDF文件阅读功能的应用,例如WPS、Chrome、UC浏览器等,此时我们可以借助于这些应用达到打开PDF文件的效果,只需要具备以下两个条件:
- PDF 文件已保存在本地;
- 用户手机中安装了支持 PDF 阅读的应用。
实现这个方案的代码示例如下:
public void openPdfFile(File file) {
Intent intent = new Intent("android.intent.action.VIEW");
intent.addCategory("android.intent.category.DEFAULT");
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Uri uri = Uri.fromFile(file);
intent.setDataAndType(uri, "application/pdf");
startActivity(Intent.createChooser(intent, "打开PDF文件"));
}
三. 使用PDFBox读取编辑PDF文件内容
PDFBox(一个BSD许可下的源码开放项目)是一个为开发人员读取和创建PDF文档而准备的纯Java类库。它提供如下特性: 提取文本,包括Unicode字符,和Jakarta Lucene等文本搜索引擎的整合过程十分简单;加密/解密PDF文档;从PDF和XFDF格式中导入或导出表单数据;向已有PDF文档中追加内容;将一个PDF文档切分为多个文档;覆盖PDF文档等。下载地址点击这里。
1. 读取PDF内容
1 public void readPDF() {
2 PDDocument helloDocument = null;
3 try {
4 helloDocument = PDDocument.load(new File(
5 "User/fqian/download/test.pdf"));
6 PDFTextStripper textStripper = new PDFTextStripper("GBK");
7 System.out.println(textStripper.getText(helloDocument));
8
9 helloDocument.close();
10 } catch (IOException e) {
11 // TODO Auto-generated catch block
12 e.printStackTrace();
13 }
14 }
这种方式允许你读取PDF文件的内容,而后进行多种形式的展示,缺点也很明显,就是会失去原有的排版样式;
2. 将PDF文件转换为图片
1 public void convert2Image() {
2 try {
3 PDDocument doc = PDDocument
4 .load("User/fqian/download/test.pdf");
5 int pageCount = doc.getPageCount();
7 List pages = doc.getDocumentCatalog().getAllPages();
8 for (int i = 0; i < pages.size(); i++) {
9 PDPage page = (PDPage) pages.get(i);
10 BufferedImage image = page.convertToImage();
11 Iterator iter = ImageIO.getImageWritersBySuffix("jpg");
12 ImageWriter writer = (ImageWriter) iter.next();
13 File outFile = new File("User/fqian/download/"
14 + i + ".jpg");
15 FileOutputStream out = new FileOutputStream(outFile);
16 ImageOutputStream outImage = ImageIO
17 .createImageOutputStream(out);
18 writer.setOutput(outImage);
19 writer.write(new IIOImage(image, null, null));
20 }
21 doc.close();
23 } catch (FileNotFoundException e) {
24 // TODO Auto-generated catch block
25 e.printStackTrace();
26 } catch (IOException e) {
27 // TODO Auto-generated catch block
28 e.printStackTrace();
29 }
30 }
这种方式避免了直接读取文件内容再进行显示造成的样式缺失问题,但是当文件体积较大时,生成的图片所占空间也随之暴涨,因此客户端进行请求时面对的加载时间和流量耗费问题是比较尴尬的。
四. 集成第三方SDK,实现本地阅读
事实上,已经存在了为数不少的免费或者付费的 PDF SDK,一般而言免费版在功能和性能等指标上与收费版可能存在一定差距。这种方式的优点是加载速度快和节约流量,缺点是会显著的增加安装包大小,例如 AndroidPdfViewer 的引入,剔除不常用的处理器架构,只保留 armeabi-v7a 和 x86,还是会增加将近 10M 的大小。
免费版:
- PDFium:Google 和 Foxit 合作开源的 Foxit 的 PDF 源码,作为 Chrome 浏览器的 PDF 渲染引擎组件,当然这是 C/C++ 实现的;
- PdfiumAndroid:mshockwave 基于 PDFium 基础上适配 Android 平台的函数库;
- AndroidPdfViewer:barteksc 基于 PdfiumAndroid 基础上实现的一个 PDF 阅读 Demo,支持常见的手势,缩放,双击等效果。
- MuPDF: 一个轻量级的 开源 PDF 和 XPS 查看器
付费版:
- Foxit 福昕 SDK:国内老牌的付费 PDF SDK,功能强大,如果 PDF 阅读功能在你的应用中比较常用但又不是核心功能,可以考虑接入它;
- PlugPDF:国外的一款付费 PDF SDK,类似 Foxit SDK;
五. 集成Mozilla的PDF.js,在 WebView 中阅读PDF文件
PDF.js 是由Mozilla 主导推出的可以将PDF文件转换为H5页面进行展示的工具,有服务端和客户端两种集成方式来实现在 WebView 中打开 PDF 文件的功能。关于更多PDF.js的官方描述,请点击这里。
1. 服务端方式
PDF.js 提供了一套较完善的在 H5 页面中阅读 PDF 的方案,同时支持 Web 前端,Android 和 iOS WebView 加载。服务部署起来应该也比较简单,大致的方案如下:
- 服务段创建一个HTML页面,该页面使用
- 客户端获取到HTML页面对应的URL;
- 客户端通过 WebView 加载该页面。
更具体的方案需要服务端开发人员自行商议决定,大致流程点击这里。
2. 客户端方式
PDF.js 也支持客户端集成方式,客户端需要把官方提供的 pdf.js 和 pdf.worker.js 拷贝到工程的 assets 目录,同时在该目录下实现一个离线 H5 页面,该页面通过上述两个 js 文件实现 PDF 的阅读。该方案的缺点主要有三个:
- 客户端起码增加 1~2M 的体积;
- H5 页面的交互和设计需要重新实现,这部分的工作量就比较可观了;
- 加载体积较大的PDF文件时耗时较长。
六. 使用 pdf2htmlEX 将PDF 文件转换成 HTML 或者图片
pdf2htmlEX 是由国内王路同学发布的,可以实现绝大部分PDF文件转换为HTML文件的操作,服务端通过调用命令行预先将PDF文件转换为HTML文件,而后向客户端暴露URL,客户端通过WebView的方式加载即可。官方预览点击这里。
1. 安装(官方安装指南请点击这里)
pdf2htmlEX只能部署于类Unix环境,具体支持的系统环境列表如下:
- Linux (for Ubuntu 12.10+)
- OS X
- Windows/Cygwin
- Windows/Mingw-w64
- Windows/MinGW, 需要对pdf2htmlEX做出部分修改. 详情请点击这里pdf2htmlEX on TeX Wiki (in Japanese) Ps.日语不好的同学请加强学习......
Mac OS X
官方推荐使用brew来安装,安装完brew后可以使用以下命令安装 pdf2htmlEX:
brew install pdf2htmlEX
Windows
在Windows下安装pdf2htmlEX,需要借助于MSYS2 + mingw-w64,具体流程点击这里。
Fedora
在Fedora发行版本下需要添加如下依赖:
sudo yum install cmake gcc gnu-getopt java-1.8.0-openjdk libpng-devel fontforge-devel cairo-devel poppler-devel libspiro-devel freetype-devel poppler-data libjpeg-turbo-devel git make gcc-c++
2. 使用(官方使用指南请点击这里)
(1). 简单的转换为HTML
pdf2htmlEX --zoom 1.3 pdf/test.pdf
会在当前目录生成一个同名的HTML文件
- zoom:表示缩放 后面的数字就是缩放比例,数字越小,生成的HTML显示界面越小,但是本身的bytes大小不受影响
- pdf/test.pdf:是文件路径,相对于当前目录的路径
pdf2htmlEX -f 3 -l 5 --fit-width 1024 --bg-format jpg pdf/test.pdf
- f:起始页码
- l:结束页码
- fit-width:页面宽度
- bg_format: 背景图片格式
(2). 转换为复杂的目录(包含HTML,CSS,IMGS,FONTS)
pdf2htmlEX --embed cfijo --dest-dir out pdf/test.pdf
会在指定目录生成一个同名的html文件及附带的资源文件,各类资源文件(例如fonts、imgs、css和javascript)分别存储在不同目录,这样展示界面可以更好的利用浏览器缓存的优势
- embed cfijo:没有实际意义,是本身命令,不需要修改
- out:自定义文件夹名称,所有的转换的文件都生成在此目录
- pdf/test.pdf:源pdf文件
pdf2htmlEX --embed cfijo --split-pages 1 --dest-dir out --page-filename test-%d.page pdf/test.pdf
效果同上面的命令类似,但是会将每页分别存储于单独的文件目录,这些目录将会按照命令中的规则那样会被分别命名为test-0.page, test-1.page等等。同事依然会有一个同名HTML文件通过ajax动态加载页面,通过这种方式,发布者可以获得足够的权限去自由控制页面,例如延迟加载。
除了以上的命令以外,还有很多实用方式,比如截取片段转换、修改像素等,这里不再赘述,感兴趣的可以去官网查看。