Word转换HTML(Java实用版)
前言:
在业务中,如果需要在浏览器中预览Word文档,或者需要将Word文档转成HTML文件保存,那么本章内容,可以帮助到你。
实现这一功能,有多种实现方式,如:docx4j、poi、Free Spire.Doc for Java、openoffice、jacob都可以实现转换功能,但都有局限性。在这稍微介绍一下哈,大家可做个对比
docx4j
docx4j主要是针对docx文件进行操作,操作的对象的Microsoft Open XML文件。
java当中用于操作office(docx/xlsx/ppt)等文件的类库
poi
POI是Apache软件基金会的开放源码函式库,POI提供API给Java程序对Microsoft Office格式档案读和写的功能。
结构:
HSSF - 提供读写Microsoft Excel格式档案的功能。
XSSF - 提供读写Microsoft Excel OOXML格式档案的功能。
HWPF - 提供读写Microsoft Word格式档案的功能。
HSLF - 提供读写Microsoft PowerPoint格式档案的功能。
HDGF - 提供读写Microsoft Visio格式档案的功能。
Free Spire.Doc for Java(功能强大,但可以收费)
Free Spire.Doc for Java 是一款免费、专业的 Java Word 组件,开发人员使用它可以轻松地将 Word 文档创建、读取、编辑、转换和打印等功能集成到自己的 Java 应用程序中。作为一款完全独立的组件,Free Spire.Doc for Java的运行环境无需安装 Microsoft Office。
友情提示:免费版有篇幅限制。在加载或保存 Word 文档时,要求 Word 文档不超过 500 个段落,25 个表格。同时将 Word 文档转换为 PDF 和 XPS 等格式时,仅支持转换前三页
openoffice
一、利用jodconverter(基于OpenOffice服务)将文件(.doc、.docx、.xls、.ppt)转化为html格式。
二、利用jodconverter(基于OpenOffice服务)将文件(.doc、.docx、.xls、.ppt)转化为pdf格式。需要用户安装了Adobe Reader XI
jacob(不能用于Linux)
需要引入jacob.jar jar包,并且jar包还要调用jacob.dll文件,需要事先把jacob.dll文件放到以下3处地方:C:\Windows\System32 目录下,安装的jdk文件夹下的bin目录中,以及jre文件夹下的bin目录(注意一定是你这个项目运行所用到的jdk和jre)
它允许在java中调用com接口自动组件,它使用JNI(本地调用进程)来进行本地调用COM库。它可运行在x86和支持32位和64位Java虚拟机
本文采用poi来进行转换
1、Poi转换
1.1、引入依赖
<!-- WordToHtml .doc .odcx poi -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-scratchpad</artifactId>
<version>4.1.2</version>
</dependency>
<!-- 操作excel的库 注意版本保持一致 poi poi-ooxml poi-scratchpad -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>4.1.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.1.2</version>
</dependency>
<dependency>
<groupId>fr.opensagres.xdocreport</groupId>
<artifactId>fr.opensagres.poi.xwpf.converter.xhtml</artifactId>
<version>2.0.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/fr.opensagres.xdocreport/fr.opensagres.xdocreport.converter.docx.xwpf -->
<dependency>
<groupId>fr.opensagres.xdocreport</groupId>
<artifactId>fr.opensagres.xdocreport.converter.docx.xwpf</artifactId>
<version>2.0.1</version>
</dependency>
1.2、工具类
poi转换工具类
/**
* poi WordToHtml工具类
*/
@Slf4j
public class WordToHtml {
// 文件上传保存路径
@Value(value = "${upload.path}")
private final String uploadPath = "";
//转换的方法
public File convert(MultipartFile file) {
//获得文件的名字
String filename = file.getOriginalFilename();
//获得文件的扩展名
String suffix = filename.substring(filename.lastIndexOf("."));
String newName = UUID.randomUUID().toString();
// TODO 需要保存在一个新的位置
// File =new File 表示目录的一个抽象,可以进一步用exists()和isDirectory()方法判断。
File convFile = new File(uploadPath + newName + suffix);
FileOutputStream fos = null;
try {
//创建文件
convFile.createNewFile();
//FileOutputStream 是输出流 将文件输出到磁盘或者数据库中
fos = new FileOutputStream(convFile);
fos.write(file.getBytes());
} catch (IOException ex) {
log.error("上传文件出错!", ex);
return null;
} finally {
IOUtils.closeQuietly(fos);
}
// 输入文件名的所在文件夹
// 加上反斜杠
String parentDirectory = convFile.getParent();
if (!parentDirectory.endsWith("\\")) {
parentDirectory = parentDirectory + "\\";
}
if (filename.endsWith(".docx")) {
return docxConvert(parentDirectory, convFile.getAbsolutePath(), newName);
} else if (filename.endsWith(".doc")) {
return docConvert(parentDirectory, convFile.getAbsolutePath(), newName);
} else {
log.error("不支持的文件格式!");
return null;
}
}
/**
* html 流文件 修改内容 width:595.3pt; 因为转换的HTML页面默认内容区域不是html自适应大小,内容位置不对
* @param parentDirectory html文件所在文件夹
* @param filename html旧文件地址
* @param newName html新文件地址
* @return
*/
private File htmlreplace(String parentDirectory, String filename, String newName) {
try {
// 读取生成的Html
FileInputStream inputStream = new FileInputStream(new File(parentDirectory + filename + ".html"));
InputStream inputStrem = readInputStrem(inputStream);
// 清空文件内容
clearInfoForFile(parentDirectory + filename + ".html");
// TODO: 2022/4/22 进行流输出Html文件 inputStrem
// 1、读取内容
byte[] buffer = new byte[inputStrem.available()];
inputStrem.read(buffer);
// 写入内容
OutputStream outStream = new FileOutputStream(new File(parentDirectory + newName + ".html"));
outStream.write(buffer);
return new File(parentDirectory + newName + ".html");
} catch (FileNotFoundException e) {
log.error("Html转换失败!",e);
return null;
} catch (IOException e) {
log.error("Html转换失败!",e);
return null;
}
}
/**
* 读取HTML 流文件,并查询当中的width:595.3pt; / white-space:pre-wrap; 或类似符号直接替换为空格
*
* @param inputStream
* @return
*/
private static InputStream readInputStrem(InputStream inputStream) {
// 匹配内容
String regEx_special = "width:595.3pt;";
String regEx_special2 = "white-space:pre-wrap;";
// 替换新内容
String replace = "white-space:pre-wrap;word-break:break-all;";
try {
//<1>创建字节数组输出流,用来输出读取到的内容
ByteArrayOutputStream baos = new ByteArrayOutputStream();
//<2>创建缓存大小
byte[] buffer = new byte[1024]; // 1KB
//每次读取到内容的长度
int len = -1;
//<3>开始读取输入流中的内容
while ((len = inputStream.read(buffer)) != -1) { //当等于-1说明没有数据可以读取了
baos.write(buffer, 0, len); //把读取到的内容写到输出流中
}
//<4> 把字节数组转换为字符串
String content = baos.toString();
//<5>关闭输入流和输出流
// inputStream.close();
baos.close();
// log.info("读取的内容:{}", content);
// 判断HTML内容是否具有HTML的 width:595.3pt;
Pattern compile = Pattern.compile(regEx_special, Pattern.CASE_INSENSITIVE);
Matcher matcher = compile.matcher(content);
String replaceAll = matcher.replaceAll("");
// 判断是否具有white-space:pre-wrap;
Pattern compile2 = Pattern.compile(regEx_special2, Pattern.CASE_INSENSITIVE);
Matcher matcher2 = compile2.matcher(replaceAll);
String replaceAll2 = matcher2.replaceAll(replace);
// log.info("替换后的内容:{}", replaceAll2);
// 将字符串转化为输入流返回
InputStream stringStream = getStringStream(replaceAll2);
//<6>返回结果
return stringStream;
} catch (Exception e) {
e.printStackTrace();
log.error("错误信息:{}", e.getMessage());
return null;
}
}
/**
* 将一个字符串转化为输入流
* @param sInputString 字符串
* @return
*/
public static InputStream getStringStream(String sInputString) {
if (sInputString != null && !sInputString.trim().equals("")) {
try {
ByteArrayInputStream tInputStringStream = new ByteArrayInputStream(sInputString.getBytes());
return tInputStringStream;
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
/**
* 清空文件内容
* @param fileName
*/
public static void clearInfoForFile(String fileName) {
File file =new File(fileName);
try {
if(!file.exists()) {
file.createNewFile();
}
FileWriter fileWriter =new FileWriter(file);
fileWriter.write("");
fileWriter.flush();
fileWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 转换.docx 当word文档字体大于5号字体时,会出现不规律排列文字换行(因为转换的HTML页面默认内容区域不是html原始区域)
* @param parentDirectory html文件所在文件夹 (主要用于图像的管理)
* @param filename word文件地址
* @param newName html文件地址
* @return
*/
private File docxConvert(String parentDirectory, String filename, String newName) {
try {
// 1) 加载word文档生成 XWPFDocument对象
XWPFDocument document = new XWPFDocument(new FileInputStream(filename));
// 设置存放图片地址
XHTMLOptions options = XHTMLOptions.create().setImageManager(new ImageManager(new File(parentDirectory), UUID.randomUUID().toString())).indent(4);
OutputStream out = new FileOutputStream(new File(parentDirectory + newName + ".html"));
// 自定义编码格式
OutputStreamWriter writer = new OutputStreamWriter(out,"GBK");
// 生成HTML
XHTMLConverter xhtmlConverter = (XHTMLConverter)XHTMLConverter.getInstance();
xhtmlConverter.convert(document, writer, options);
// 将生成的HTML进行内容匹配替换
File htmlreplace = htmlreplace(parentDirectory, newName, newName);
return htmlreplace;
// return new File(parentDirectory + newName + ".html");
} catch (IOException ex) {
log.error("word转化出错!", ex);
return null;
}
}
/**
* 转换.doc
* @param parentDirectory html文件所在文件夹 (主要用于图像的管理)
* @param filename word文件地址
* @param newName html文件地址
* @return
*/
private File docConvert(String parentDirectory, String filename, String newName) {
try {
HWPFDocument document = new HWPFDocument(new FileInputStream(filename));
WordToHtmlConverter wordToHtmlConverter = new WordToHtmlConverter(
DocumentBuilderFactory.newInstance().newDocumentBuilder()
.newDocument());
// converter默认对图片不作处理,需要手动下载图片并嵌入到html中
wordToHtmlConverter.setPicturesManager(new PicturesManager() {
@Override
public String savePicture(byte[] bytes, PictureType pictureType, String s, float v, float v1) {
String imageFilename = parentDirectory + "";
String identity = UUID.randomUUID().toString();
File imageFile = new File(imageFilename, identity + s);
imageFile.getParentFile().mkdirs();
InputStream in = null;
FileOutputStream out = null;
try {
in = new ByteArrayInputStream(bytes);
out = new FileOutputStream(imageFile);
IOUtils.copy(in, out);
} catch (IOException ex) {
log.error("word转化出错!", ex);
} finally {
if (in != null) {
IOUtils.closeQuietly(in);
}
if (out != null) {
IOUtils.closeQuietly(out);
}
}
return imageFile.getName();
}
});
wordToHtmlConverter.processDocument(document);
Document htmlDocument = wordToHtmlConverter.getDocument();
ByteArrayOutputStream out = new ByteArrayOutputStream();
DOMSource domSource = new DOMSource(htmlDocument);
StreamResult streamResult = new StreamResult(out);
// 设置转换属性
TransformerFactory tf = TransformerFactory.newInstance();
Transformer serializer = tf.newTransformer();
serializer.setOutputProperty(OutputKeys.ENCODING, "GBK");
serializer.setOutputProperty(OutputKeys.INDENT, "yes");
serializer.setOutputProperty(OutputKeys.METHOD, "html");
serializer.transform(domSource, streamResult);
out.close();
String result = new String(out.toByteArray());
FileWriter writer = new FileWriter(parentDirectory + newName + ".html");
writer.write(result);
writer.close();
} catch (IOException | TransformerException | ParserConfigurationException ex) {
log.error("word转化出错!", ex);
}
return new File(parentDirectory + newName + ".html");
}
/**
* 将上传的Word文档转化成HTML字符串
*
* @param file
* @return
*/
public String convertToHtml(MultipartFile file) {
String wordContent = "";
// 将Word文件转换为html
File file2 = convert(file);
// 读取html文件
if (file2 != null) {
return "文件转换成功";
}
return "文件转换失败";
}
/**
* wordToHtml
* @param wordFilePath word文件路径
* @param htmlFilePath html文件路径
* @throws IOException
* @throws ParserConfigurationException
* @throws TransformerException
*/
public static File wordToHtml(String wordFilePath,String htmlFilePath) {
// 提取出word文档名称和后缀
String filename = wordFilePath.substring(wordFilePath.lastIndexOf("/")+1);
// 提取出html文件存放路径和文件名称
String newName = htmlFilePath.substring(htmlFilePath.lastIndexOf("/")+1,htmlFilePath.lastIndexOf("."));
File convFile = new File(htmlFilePath);
// 输入文件名的所在文件夹
// 加上反斜杠
String parentDirectory = convFile.getParent();
if (!parentDirectory.endsWith("\\")) {
parentDirectory = parentDirectory + "\\";
}
if (filename.endsWith(".docx")) {
return new WordToHtml().docxConvert(parentDirectory, wordFilePath, newName);
} else if (filename.endsWith(".doc")) {
return new WordToHtml().docConvert(parentDirectory, wordFilePath, newName);
} else {
log.error("不支持的文件格式!");
return null;
}
}
}
1.3、测试类
/**
* @Author:wk
* @Create:2022/4/21/15:10
* @Description:WordToHtml测试类 poi
* @Version:1.0
*/
@Slf4j
public class WordToHtmlTest {
public static void main(String[] args) {
long timeMillis = System.currentTimeMillis();
log.info("开始转换!");
String wordFilePath = "src/main/resources/word/nc.docx";
String htmlFilePath = "src/main/resources/html/nc5.html";
File file = WordToHtml.wordToHtml(wordFilePath, htmlFilePath);
// 读取html文件
if (file != null) {
log.info("文件存放路径:{}",file.getPath());
log.info("转换结束!用时:{}ms",System.currentTimeMillis()-timeMillis);
return;
}
log.error("文件转换失败!");
}
}
测试效果(真实效果存在较小差异)由于截图一页显示不全,所以文档和页面都做了响应调整哈
.doc
.docx(文档是一样的, 此处就不截屏了哈)
Word转换HTML(Java实用版)的更多相关文章
- java将Word转换成PDF方法
转载1:java将Word转换成PDF三种方法_pdfoptions_Zhsh-7的博客-CSDN博客 转载2:POI 实现 word转成pdf - 挽留匆匆的美丽 - 博客园 (cnblogs.co ...
- 去掉word冗余格式 java正则表达式
word转换html时,会留下很多格式,有些格式并不是我们所需要的,然而这些格式比真正的文章内容还要多,严重影响页面的加载速度,因此就需要找个一个好的解决方案把这些多余的格式个去掉.网上有很多去除wo ...
- 【文件】使用jacob将word转换成pdf格式
使用jacob将word转换成pdf格式 1.需要安装word2007或以上版本,若安装07版本学确保该版本已安装2downbank0204MicrosoftSaveasPDF_ XPS,否则安装 ...
- C#将Word转换成PDF方法总结(基于Office和WPS两种方案)
有时候,我们需要在线上预览word文档,当然我们可以用NPOI抽出Word中的文字和表格,然后显示到网页上面,但是这样会丢失掉Word中原有的格式和图片.一个比较好的办法就是将word转换成pdf,然 ...
- Gson把json串转换成java实体对象
Gson把json串转换成java实体对象的方法如下: 1.首先导入Gson的jar包,网上可以下载. java实体对象如下: public class Model { private double ...
- mac 环境下 Quantlib 使用Swig 转换到java
一.Mac安装boost方法:http://blog.csdn.net/xujiezhige/article/details/8230493 二.Swig,这里使用sudo install swig ...
- json字符串转json对象,json对象转换成java对象
@RequestMapping(value = "updateInvestorApplyAccountNo", method = RequestMethod.POST) @Resp ...
- VSTO中Word转换Range为Image的方法
VSTO中Word转换Range为Image的方法 前言 VSTO是一套用于创建自定义Office应用程序的Visual Studio工具包,通过Interop提供的增强Office对象,可以对Wor ...
- word转换成HTML 以及IE不兼容问题
public static bool WordToHtml(string wordFileName, string htmlFileName) { try { Object oMissing = Sy ...
- 转换成json字符串,与json字符串转换成java类型都要先转换成json对象
转换成json字符串,与json字符串转换成java类型都要先转换成json对象
随机推荐
- 开心档之MySQL ALTER命令
MySQL ALTER命令 当我们需要修改数据表名或者修改数据表字段时,就需要使用到MySQL ALTER命令. 开始本章教程前让我们先创建一张表,表名为:testalter_tbl. root@ho ...
- 数据库mysql8.0安装+Navicat12
第一次写博客,准备坚持下去把每天学习到的东西记录下来,刚好安装mysql8.0过程中遇到了一些问题并解决,系统win10.致敬博客 首先先粘贴一段mysql的百度百科词条:MySQL是一个关系型数据库 ...
- 轻量化3D文件格式转换HOOPS Exchange新特性
BIM与AEC市场发展现状 近年来BIM(建筑信息模型)和AEC(建筑.工程和施工)市场一直保持着持续增长.2014 年全球 BIM 软件市场价值 27.6 亿美元,而到 2022年,预期到达115. ...
- ABC267G Increasing K Times 题解
做这道题,很有感悟,发篇文. 先给数列从小到大排个序. 接下来设 \(f_{i,j}\) 表示前 \(i\) 个数的排列形成 \(j\) 个上坡的方案数. 接下来考虑转移,分为插入第 \(i\) 个数 ...
- 1分钟了解C语言正确使用字节对齐及#pragma pack的方法
C/C++编译器的缺省字节对齐方式为自然对界.即在缺省情况下,编译器为每一个变量或是数据单元按其自然对界条件分配空间. 在结构中,编译器为结构的每个成员按其自然对界(alignment)条件分配空 ...
- 2023-03-20:给定一个无向图,保证所有节点连成一棵树,没有环, 给定一个正数n为节点数,所以节点编号为0~n-1,那么就一定有n-1条边, 每条边形式为{a, b, w},意思是a和b之间的无
2023-03-20:给定一个无向图,保证所有节点连成一棵树,没有环, 给定一个正数n为节点数,所以节点编号为0~n-1,那么就一定有n-1条边, 每条边形式为{a, b, w},意思是a和b之间的无 ...
- 2022-09-18:以下go语言代码输出什么?A:1;B:15;C:panic index out of range;D:doesn’t compile。 package main import
2022-09-18:以下go语言代码输出什么?A:1:B:15:C:panic index out of range:D:doesn't compile. package main import ( ...
- 2022-04-22:给你一个大小为 m x n 的矩阵 board 表示甲板,其中,每个单元格可以是一艘战舰 ‘X‘ 或者是一个空位 ‘.‘ ,返回在甲板 board 上放置的 战舰 的数量。 战舰
2022-04-22:给你一个大小为 m x n 的矩阵 board 表示甲板,其中,每个单元格可以是一艘战舰 'X' 或者是一个空位 '.' ,返回在甲板 board 上放置的 战舰 的数量. 战舰 ...
- 2020-02-24:arr是面值数组,其中的值都是正数且没有重复。再给定一个正数aim。每个值都认为是一种面值,且认为张数是无限的。返回组成aim的最少货币数。
福哥答案2020-02-24: 自然智慧即可. 1.递归.有代码. 2.动态规划.dp是二维数组.有代码. 代码用golang编写,代码如下: package main import ( " ...
- 2022-02-21:不含连续1的非负整数。 给定一个正整数 n ,返回范围在 [0, n] 都非负整数中,其二进制表示不包含 连续的 1 的个数。 输入: n = 5 输出: 5 解释: 下面是带
2022-02-21:不含连续1的非负整数. 给定一个正整数 n ,返回范围在 [0, n] 都非负整数中,其二进制表示不包含 连续的 1 的个数. 输入: n = 5 输出: 5 解释: 下面是带有 ...