首先要感谢pdf2htmlEX的作者Lu Wang,该软件是一个pdf转html的开源软件,效果非常理想。下面两张图片是html和pdf视图下的截图:
windows下载地址pdf2htmlEX-v1.0-win32-static
本人开发的一个功能:文档在线阅读,要求能够支持移动终端浏览器在线阅读。考虑过将文档先转pdf,然后在将pdf转swf,利用flexpaper在前端浏览器访问。但是由于safari浏览器不支持flash,所以这种方式不太适合。也测试过火狐的pdf.js,但是这个框架在safari中出现中文乱码,同样不行。最后,经过测试,只有使用pdf2htmlEX转的html在各个浏览器上展示效果均不错,所以选择该软件。
第一步:下载pdf2html。
第二步:修改pdf2html自带的js文件pdf2htmlEX.min.js。原因:移动终端浏览器对CSS定位absolute的支持有问题(不会出现滚动条),所以需要为所有页面的容器设置高度,这样,手机浏览器就可以出现滚动条了。修改和添加的js代码如下:
文件最后加上:
window.οnlοad=function(){
var eles = document.getElementsByClassName('pf w0 h0');
var height = 0;
for(var i=0,len=eles.length;i0)
document.getElementById('page-container').style.height=height+'px';
}
/*注释下面这段代码,因为手机浏览器无法触发滚动事件
this.container.addEventListener('scroll', function() {
self.update_page_idx();
self.schedule_render(true);
}, false);
*/
/*新增,使用document对象上滚动加载页面数据,这样可以兼容手机浏览器*/
document.addEventListener('scroll', function() {
self.update_page_idx();
self.schedule_render(true);
}, false);
public class Pdf2htmlEXUtil {
/**
* 调用pdf2htmlEX将pdf文件转换为html文件
* @param command 调用exe的字符串
* @param pdfName 需要转换的pdf文件名称
* @param htmlName 生成的html文件名称
* @return
*/
public static boolean pdf2html(String command,String pdfName,String htmlName){
Runtime rt = Runtime.getRuntime();
try {
Process p = rt.exec(command);
StreamGobbler errorGobbler = new StreamGobbler(p.getErrorStream(), "ERROR");
// kick off stderr
errorGobbler.start();
StreamGobbler outGobbler = new StreamGobbler(p.getInputStream(), "STDOUT");
// kick off stdout
outGobbler.start();
int w = p.waitFor();
System.out.println(w);
int v = p.exitValue();
System.out.println(v);
return true;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
public static void main(String[] args) {
pdf2html("D:\\pdf2htmlEX-v1.0\\pdf2htmlEX.exe D:\\v.pdf hello.html","v.pdf","v2.html");
}
}
处理Runtime.exec()一直阻塞的类:如果没有这个类,p.waitFor()将会一直等待,这是从 这里找到的解决方法
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
/**
* 用于处理Runtime.getRuntime().exec产生的错误流及输出流
* @author shaojing
*
*/
public class StreamGobbler extends Thread {
InputStream is;
String type;
OutputStream os;
StreamGobbler(InputStream is, String type) {
this(is, type, null);
}
StreamGobbler(InputStream is, String type, OutputStream redirect) {
this.is = is;
this.type = type;
this.os = redirect;
}
public void run() {
InputStreamReader isr = null;
BufferedReader br = null;
PrintWriter pw = null;
try {
if (os != null)
pw = new PrintWriter(os);
isr = new InputStreamReader(is);
br = new BufferedReader(isr);
String line=null;
while ( (line = br.readLine()) != null) {
if (pw != null)
pw.println(line);
System.out.println(type + ">" + line);
}
if (pw != null)
pw.flush();
} catch (IOException ioe) {
ioe.printStackTrace();
} finally{
try {
if(pw!=null)
pw.close();
if(br!=null)
br.close();
if(isr!=null)
isr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
一个完整的高保真pdf转html例子就完成了。使用pdf2html,本人摸索了2天,终于在今天搞定,特此记录一下。
pdf2html命令用法:
用法: pdf2htmlEX [options] []
-f,--first-page 需要转换的起始页 (默认: 1)
-l,--last-page 需要转换的最后一页 (默认: 2147483647)
--zoom 缩放比例
--fit-width 适合宽度 像素
--fit-height 适合高度 像素
--use-cropbox 使用剪切框 (default: 1)
--hdpi 图像水平分辨率 (default: 144)
--vdpi 图像垂直分辨率 (default: 144)
--embed 指定哪些元素应该被嵌入到输出
--embed-css 将CSS文件嵌入到输出中 (default: 1)
--embed-font 将字体文件嵌入到输出中 (default: 1)
--embed-image 将图片文件嵌入到输出中 (default: 1)
--embed-javascript 将javascript文件嵌入到输出中 (default: 1)
--embed-outline 将链接嵌入到输出中 (default: 1)
--split-pages 将页面分割为单独的文件 (default: 0)
--dest-dir 指定目标目录 (default: ".")
--css-filename 生成的css文件的文件名 (default: "")
--page-filename 分割的网页名称 (default:"")
--outline-filename 生成的链接文件名称 (default:"")
--process-nontext 渲染图行,文字除外 (default: 1)
--process-outline 在html中显示链接 (default: 1)
--printing 支持打印 (default: 1)
--fallback 在备用模式下输出 (default: 0)
--embed-external-font 嵌入局部匹配的外部字体 (default: 1)
--font-format 嵌入的字体文件后缀 (ttf,otf,woff,svg) (default: "woff")
--decompose-ligature 分解连字-> fi (default:0)
--auto-hint 使用fontforge的autohint上的字体时不提示 (default: 0)
--external-hint-tool 字体外部提示工具 (overrides --auto-hint) (default: "")
--stretch-narrow-glyph 伸展狭窄的字形,而不是填充 (default: 0)
--squeeze-wide-glyph 收缩较宽的字形,而不是截断 (default: 1)
--override-fstype clear the fstype bits in TTF/OTF fonts (default:0)
--process-type3 convert Type 3 fonts for web (experimental) (default: 0)
--heps 合并文本的水平临界值,单位:像素(default: 1)
--veps vertical threshold for merging text, in pixels (default: 1)
--space-threshold 断字临界值 (临界值 * em) (default:0.125)
--font-size-multiplier 一个大于1的值增加渲染精度 (default: 4)
--space-as-offset 把空格字符作为偏移量 (default: 0)
--tounicode 如何处理ToUnicode的CMap (0=auto, 1=force,-1=ignore) (default: 0)
--optimize-text 尽量减少用于文本的HTML元素的数目 (default: 0)
--bg-format 指定背景图像格式 (default: "png")
-o,--owner-password 所有者密码 (为了加密文件)
-u,--user-password 用户密码 (为了加密文件)
--no-drm 覆盖文档的 DRM 设置 (default: 0)
--clean-tmp 转换后删除临时文件 (default: 1)
--data-dir 指定的数据目录 (default: ".\share\pdf2htmlEX")
--debug 打印调试信息 (default: 0)
-v,--version 打印版权和版本信息
-h,--help 打印使用帮助信息
本人使用的版本时v0.11的和v1的版本有一些区别,主要是作者重新编写了pdftohtmlEX.js所以需要对照上面的js做相应修改
window.οnlοad=function(){
var eles = document.getElementsByClassName('pd w0 h0');
var height = 0;
for(var i=0,len=eles.length;i0){
document.getElementById('page-container').style.height=height+'px';
document.getElementById('page-container').style.overflow='hidden';
}
}
//this.$container.scroll(function(){ _.schedule_render(); });
$(document).scroll(function(){_.schedule_render();});
修改之后的Pdf2htmlEXUtil
package cn.com.oims.util;
import cn.com.oims.config.BaseConfig;
/**@author liuzhengyong
* @version 1.0 时间:2013-12-30 下午2:24:10
* pdf文件转html工具类
*/
public class Pdf2htmlEXUtil {
private static final int OS = 2;
/**
* 调用pdf2htmlEX将pdf文件转换为html文件
* @param exeFilePath pdf2htmlEX.exe文件路径
* @param pdfFile pdf文件绝对路径
* @param [destDir] 生成的html文件存放路径
* @param htmlName 生成的html文件名称
* @return
*/
public static boolean pdf2html(String exeFilePath,String pdfFile,String destDir,String htmlFileName){
if(OS==2){//linux
return pdf2html_linux(htmlFileName, htmlFileName, htmlFileName);
}
if(!(exeFilePath!=null&&!"".equals(exeFilePath)
&&pdfFile!=null&&!"".equals(pdfFile)
&&htmlFileName!=null&&!"".equals(htmlFileName))){
System.out.println("传递的参数有误!");
return false;
}
Runtime rt = Runtime.getRuntime();
StringBuilder command = new StringBuilder();
command.append(exeFilePath).append(" ");
if(destDir!=null&&!"".equals(destDir.trim()))//生成文件存放位置,需要替换文件路径中的空格
command.append("--dest-dir ").append(destDir.replace(" ", "\" \"")).append(" ");
command.append("--optimize-text 1 ");//尽量减少用于文本的HTML元素的数目 (default: 0)
command.append("--zoom 1.4 ");
command.append("--process-outline 0 ");//html中显示链接:0——false,1——true
command.append("--font-format woff ");//嵌入html中的字体后缀(default ttf) ttf,otf,woff,svg
command.append(pdfFile.replace(" ", "\" \"")).append(" ");//需要替换文件路径中的空格
if(htmlFileName!=null&&!"".equals(htmlFileName.trim())){
command.append(htmlFileName);
if(htmlFileName.indexOf(".html")==-1)
command.append(".html");
}
try {
System.out.println("Command:"+command.toString());
Process p = rt.exec(command.toString());
StreamGobbler errorGobbler = new StreamGobbler(p.getErrorStream(), "ERROR");
//开启屏幕标准错误流
errorGobbler.start();
StreamGobbler outGobbler = new StreamGobbler(p.getInputStream(), "STDOUT");
//开启屏幕标准输出流
outGobbler.start();
int w = p.waitFor();
int v = p.exitValue();
if(w==0&&v==0){
return true;
}
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
public static boolean pdf2html_linux(String pdfFile,String destDir,String htmlFileName){
if(!(pdfFile!=null&&!"".equals(pdfFile)
&&htmlFileName!=null&&!"".equals(htmlFileName))){
System.out.println("传递的参数有误!");
return false;
}
Runtime rt = Runtime.getRuntime();
StringBuilder command = new StringBuilder();
command.append("pdf2htmlEX").append(" ");
if(destDir!=null&&!"".equals(destDir.trim()))//生成文件存放位置,需要替换文件路径中的空格
command.append("--dest-dir ").append(destDir.replace(" ", "\" \"")).append(" ");
command.append("--optimize-text 1 ");//尽量减少用于文本的HTML元素的数目 (default: 0)
command.append("--process-outline 0 ");//html中显示链接:0——false,1——true
command.append("--font-format woff ");//嵌入html中的字体后缀(default ttf) ttf,otf,woff,svg
command.append(pdfFile.replace(" ", "\" \"")).append(" ");//需要替换文件路径中的空格
if(htmlFileName!=null&&!"".equals(htmlFileName.trim())){
command.append(htmlFileName);
if(htmlFileName.indexOf(".html")==-1)
command.append(".html");
}
try {
System.out.println("Command:"+command.toString());
Process p = rt.exec(command.toString());
StreamGobbler errorGobbler = new StreamGobbler(p.getErrorStream(), "ERROR");
//开启屏幕标准错误流
errorGobbler.start();
StreamGobbler outGobbler = new StreamGobbler(p.getInputStream(), "STDOUT");
//开启屏幕标准输出流
outGobbler.start();
int w = p.waitFor();
int v = p.exitValue();
if(w==0&&v==0){
return true;
}
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
}
在dos环境下的调用命名:
D:\\pdf2htmlEX-v1.0\\pdf2htmlEX.exe d:\\test" "2 D:\\test" "1\\v1.pdf [v3.html]
D:\\pdf2htmlEX-v1.0\\pdf2htmlEX.exe表示exe文件路径。后面的空格不能少
d:\\test" "2表示转换之后的html存放位置,这里的" "为空格,dos环境下,所有空格必须使用""包裹,否则不能识别。后面的空格不能少
D:\\test" "1\\v1.pdf表示pdf文件的位置。后面的空格不能少
v3.html表示将pdf转为html文件的文件名。可选