因为自己的任务需要用到word转html,但是poi3.1.2的版本与我poi4.1.2版本冲突,所以尝试用4.1.2版本来写一个word转html,它是可以同时支持doc和docx两种格式,非常好用,当前文章是关于docx转html的,doc相对来说比较简单,有兴趣的可以尝试一下
本文章暂时为docx转html!!!!
开发工具:idea
项目管理工具:maven
不多说,直接撸代码
1、首先配置pom.xml文件,具体配置如下
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.1.2</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</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>
poi与poi-ooxml的版本需要一致。
2.工具类的开发
/**
* word 转html
*
* @param wordFile wordFile
*/
public static Map<String, String> docsToHtml(File wordFile) {
log.info("word to html beginning....");
//这个地方设置了html的文件名,ColumnEnum.FileColumn.HTML是我定义的类型 即".html"
String htmlName = RandomNum.getRandomString(8) +
System.currentTimeMillis() + ColumnEnum.FileColumn.HTML;
int dateTime = LocalDateUtil.getCurrentDateValue();
Map<String, String> fileCollect = new HashMap<>(0);
try {
@Cleanup InputStream in = new FileInputStream(wordFile);
//获取根目录名称 临时文件目录
String templatePath = System.getProperty("user.dir").substring(0, System.getProperty("user.dir").indexOf(":") + 1) + "/logback/template/";
//判断文件名是否为docx
if (!wordFile.getName().endsWith(ColumnEnum.FileColumn.DOCX)) {
return null;
}
// 1.加载解析docx文档用的XWPFDocument对象
XWPFDocument document = new XWPFDocument(in);
// 2.解析XHTML配置 设置图片链接
XHTMLOptions options = XHTMLOptions.create();
//3.将word中图片保存到云服务器 这个地方需要注意
options.setImageManager(new ImageManagerImpl());
options.setIgnoreStylesIfUnused(false);
options.setFragment(true);
//为html文件添加头
@Cleanup OutputStream out = new FileOutputStream(templatePath + htmlName);
//这个地方要注意一下 后文会有讲解
out.write(("<head>" +
"<meta http-equiv=\"Content-Type\" content=\"text/html;charset=\"UTF-8\"/>" +
"<meta name=\"viewport\" content=\"initial-scale=1.0, maximum-scale=1, minimum-scale=1, user-scalable=no,uc-fitscreen=yes\" />" +
"<style>body {margin: 0; font-family: \"Noto Sans SC\";}" +
"img {width: 100% !important;height: auto !important;} " +
//font-size: 40px; 设置字统一大小
"span{overflow-wrap: break-word}" +
"div{ width: auto !important; margin-left: 10% !important; margin-right: 10% !important;}" +
"</style>" +
"</head>").getBytes(StandardCharsets.UTF_8));
//将XWPFDocument转换成XHTML
XHTMLConverter.getInstance().convert(document, out, options);
//将html文件上传到oss
File htmlFile = new File(templatePath + htmlName);
//获取图片路径
getImagePath(htmlFile, fileCollect);
//图片上传到云服务器
OssUtil.upload(htmlFile, AliConfig.PATH + dateTime + "/" + htmlName);
//删除临时文件
htmlFile.deleteOnExit();
log.info("word to html completed....");
} catch (IOException e) {
log.info("word to html has some problems", e);
}
//返回保存路径
fileCollect.put("htmlPath", AliConfig.OSS_LINK + AliConfig.PATH + dateTime + "/" + htmlName);
//判断urlmap为空
if (ObjectUtils.isEmpty(fileCollect)) {
return null;
}
fileCollect内存储的是html地址以及图片地址 按需
return fileCollect;
}
/**
* 获取html文件中的图片路径
*
* @param htmlFile html文件
*/
private static void getImagePath(File htmlFile, Map<String, String> resultMap) {
try {
//读取html文件的每一行
List<String> lines = FileUtils.readLines(htmlFile, StandardCharsets.UTF_8);
lines.forEach(line -> {
if (StringUtils.isEmpty(line)) {
return;
}
//获取html文件中图片
String patternString = "<img\\b[^<>]*?\\bsrc[\\s]*=[\\s|'|\"]*([^\\s|'|\"]*)[\\s|'|\"]*";
Pattern patten = Pattern.compile(patternString);
Matcher matcher = patten.matcher(line);
while (matcher.find()) {
String src = matcher.group(1);
String fileNmae = src.substring(src.lastIndexOf("/") + 1);
resultMap.put(fileNmae, src);
}
});
} catch (IOException e) {
log.error("get image path has error", e);
}
}
这里首先要注意的是 XHTMLOptions options = XHTMLOptions.create();
options.setImageManager(new ImageManagerImpl());
标红的地方, options.setImageManager()设置的是word内图片存储的位置,由于我需要生成的html文件在任何地方都可以访问到包括内部图片,所以自己定义了一个类来继承ImageManager,在我定义的类中来配置word内图片保存的位置。如下代码所示
public class ImageManagerImpl extends ImageManager {
private byte[] picture;
private String suffix;
public ImageManagerImpl() {
super(new File(""), "");
}
@Override
public void extract(String imagePath, byte[] imageData) throws IOException {
this.suffix = "." + imagePath.split("\\.")[1];
this.picture = imageData;
}
@Override
public String resolve(String uri) {
//图片保存位置
String path = AliConfig.PATH + LocalDateUtil.getCurrentDateValue() + "/" +
RandomNum.getRandomString(6) + System.currentTimeMillis() + suffix;
OssUtil.upload(path, picture);
//需要返回保存路径 这样生成的html中的src标签会替换成你设置的地址
return AliConfig.OSS_LINK + path;
}
}
有意思的是这个地方
out.write(("<head>" +
"<meta http-equiv=\"Content-Type\" content=\"text/html;charset=\"UTF-8\"/>" +
"<meta name=\"viewport\" content=\"initial-scale=1.0, maximum-scale=1, minimum-scale=1, user-scalable=no,uc-fitscreen=yes\" />" +
"<style>body {margin: 0; font-family: \"Noto Sans SC\";}" +//设置图片的大小
"img {width: 100% !important;height: auto !important;} "
"span{overflow-wrap: break-word}" +//设置边距
"div{ width: auto !important; margin-left: 10% !important; margin-right: 10% !important;}" +
"</style>" +
"</head>").getBytes(StandardCharsets.UTF_8));
因为生成的html我想让他自适应手机以及电脑,所以在转换之前写进去了这么一段话,来确保自适应。
获取图片路径
因为图片被我上传到云服务器,所以在我删除html文件的时候需要获取岛图片的地址并删除,之后我写了getImagePath()这个方法来获取,不知道还有没有其他更方便的方法,有的话可以私信我哦~
写到最后:
这串代码会有以下不足之处,很欢迎大家指出~望大家指教~ EveryBody Peace~