前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >HTML转word_讯飞语记怎么变成word文档

HTML转word_讯飞语记怎么变成word文档

作者头像
全栈程序员站长
发布2022-11-04 15:12:10
1.6K0
发布2022-11-04 15:12:10
举报
文章被收录于专栏:全栈程序员必看

大家好,又见面了,我是你们的朋友全栈君。

HTML转word

背景介绍

业务:将平台中笔记(富文本)以word形式导出。

1. 使用POI进行转化

代码语言:javascript
复制
依赖jar
poi-3.17.jar
poi-excelant-3.17.jar
poi-ooxml-3.17.jar
poi-ooxml-schemas-3.17.jar
jsoup-1.11.3.jar

1.1 思路

a). 获取HTML b). HTML标准化 c). 转化

1.2 代码示例

代码语言:javascript
复制
/**
  * HTML转word
  *
  * @param noteName 导出文件名称
  * @paramre portDirName 文件路径
  * @param researchNoteInfo 文件的html
  * @return void
  * @author Solitary
  * @date 2019/1/11 9:21
  */
public static void htmlToWord(String noteName, String reportDirName, String researchNoteInfo) throws Exception {
     //拼一个标准的HTML格式文档
    Document document = Jsoup.parse(researchNoteInfo);
    FileUtils.fileIsExist(reportDirName);
    InputStream is = new ByteArrayInputStream(document.html().getBytes("GBK"));
    OutputStream os = new FileOutputStream(reportDirName+noteName);
    inputStreamToWord(is, os);
}
    
/**
 * 把is写入到对应的word输出流os中
 *
 * @param is
 * @param os
 * @throws IOException
 */
private static void inputStreamToWord(InputStream is, OutputStream os) throws IOException {
    POIFSFileSystem fs = new POIFSFileSystem();
    DirectoryNode root = fs.getRoot();
    root.createDocument("WordDocument", is);
    fs.writeFilesystem(os);
    os.close();
    is.close();
}

1.3 思考

使用poi进行HTML转word的确很简单的,但是一个很棘手的问题就是当图片资源失效、断网的情况下,word的图片无法显示。所以使用这种方式转word显得有点鸡肋了。

2. 使用jacob进行转化

代码语言:javascript
复制
依赖jar
jacob.jar
jsoup-1.11.3.jar

2.1 思路

a). 标准化HTML b). 下载图片资源到本地 c). 替换所有img标签为<p>

2.2 代码示例

代码语言:javascript
复制
/**
* 创建空白文档_写入html_处理空白文档image_复制空白文档至最终文档
* 
* @param imgs
* @param html
* @param localpath
*/
public static String getWord(String html, String localpath, long researchId) {
// 下载图片到本地 略
// 图片在文档中的键${name} - 值图片的绝对路径    imgMap.put("${ABC}", localpath + "\\ABC.png");
Map<String, String> imgMap = new HashMap<String, String>();
// 解析html_创建空白文档_html写入空白文档
Document document = Jsoup.parse(html);
for (Element element : document.body().select("body > *")) {
sysElementText(element, localpath, imgMap);
}
createWord(localpath, "blank");
File doc = new File(localpath + File.separator + "blank.doc");
FileWriter fw;
try {
fw = new FileWriter(doc);
fw.write(document.html(), 0, document.html().length());// 写入文件
fw.flush(); // 清空FileWriter缓冲区
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
String complete = String.valueOf(researchId);
// 复制空白文档-粘贴到临时文档(相当于手动执行copy_paste)
MSOfficeGeneratorUtils officeUtils = new MSOfficeGeneratorUtils(false);
officeUtils.openDocument(localpath + File.separator + "blank.doc");
officeUtils.copy(); // 拷贝整篇文档
officeUtils.close();
officeUtils.createNewDocument();
officeUtils.paste(); // 粘贴整篇文档
// 将图片${image_name}替换为真实图片
for (Entry<String, String> entry : imgMap.entrySet())
officeUtils.replaceText2Image(entry.getKey(), entry.getValue());
officeUtils.setFont(true, false, false, "0,0,0", "20", "宋体"); // 设置字体,具体参数
officeUtils.saveAs(localpath + File.separator + complete + ".doc"); // 可生成UUID.doc文件,利用UUID防止同名
officeUtils.close(); // 关闭Office Word创建的文档
officeUtils.quit(); // 退出Office Word程序
imgMap.clear();
return complete;
}
/**
*  替换img标签为p标签
* 
* @param node 
* @param imgPath 本地图片存储路径
* @param imgMap key:${imgName} value:
*/
public static void sysElementText(Node node, String imgPath, Map<String, String> imgMap) {
if (node.childNodes().size() == 0) {
if (node.nodeName().equals("img")) {
String src = node.attr("src");
String fileName = src.substring(src.lastIndexOf("/") + 1, src.length());
Element element = new Element("p");
element.append("${"+fileName+"}");
element.attr("style", node.attr("style"));
node.replaceWith(element);
imgMap.put("${"+fileName+"}", imgPath + File.separator + fileName);
}
}
if (node.childNodes().size() > 0) {
List<Node> childNodes = node.childNodes();
for (Node node2 : childNodes) {
if (node2.nodeName().equals("img")) {
String src = node2.attr("src");
String fileName = src.substring(src.lastIndexOf("/") + 1, src.length());
Element element = new Element("p");
element.append("${"+fileName+"}");
element.attr("style", node2.attr("style"));
node2.replaceWith(element);
imgMap.put("${"+fileName+"}", imgPath + File.separator + fileName);
}
}
}
}
/**
* 创建word文档
* 
* @param localpath
* @param name
* @return
*/
public static void createWord(String localpath, String name) {
MSOfficeGeneratorUtils msOfficeUtils = new MSOfficeGeneratorUtils(false); // 整合过程设置为可见
msOfficeUtils.createNewDocument();
msOfficeUtils.saveAs(localpath + File.separator + name + ".doc");
msOfficeUtils.close();
msOfficeUtils.quit();
}

MSOfficeGeneratorUtils该类参考:http://www.cnblogs.com/liudaihuablogs/p/9761297.html

2.3 思考

该方式转换图片正常显示,唯一不足的地方在于jacob使用的是office的api,服务器必须是windows,在linux下是不能运行的,所以很奔溃。 于是,我们申请一台windows服务器,在该调用HTML转word前,发送消息给windows服务器执行生成word。之后,通过Smb服务,java中的SmbFile获取远程文件到本地。

3. 使用itext进行转化

代码语言:javascript
复制
依赖jar
itext-2.1.7.jar
itext-rtf-2.1.7.jar

3.1 思路

a). 将img标签中的src修改为本地图片路径 b). 以rtf方式导出为word

3.2 代码示例

代码语言:javascript
复制
private static void html2WordIText(String html, String noteName, String reportDirName, long researchId) {
// 图片临时存放路径
String pwd = "tmp/researchNote";
Set<String> srcSet = ImageUtils.getImgStr(html);
for (String src : srcSet) {
String srcName = src.split("[/]")[src.split("[/]").length - 1];
ImageUtils.download(src, srcName, pwd + "/" + String.valueOf(researchId));
String newSrc = pwd + "/" + String.valueOf(researchId) + "/" + srcName;
html = html.replace(src, newSrc);
}
FileUtils.fileIsExist(reportDirName);
OutputStream out = null;
try {
out = new FileOutputStream(reportDirName + noteName);
Document document = new Document(PageSize.A4);
RtfWriter2.getInstance(document, out);
document.open();
Paragraph context = new Paragraph();
// Image img = Image.getInstance("D:\\图片\\2.jpg");
// img.setAbsolutePosition(0, 0);//
// document.add(img);
StyleSheet ss = new StyleSheet();
HashMap<String, String> interfaceProps = Maps.newHashMap();
interfaceProps.put("img_baseurl", "");
List htmlList = HTMLWorker.parseToList(new StringReader(html), ss, interfaceProps);
for (int i = 0; i < htmlList.size(); i++) {
com.lowagie.text.Element e = (com.lowagie.text.Element) htmlList.get(i);
context.add(e);
}
document.add(context);
document.close();
FileUtils.deletefile(pwd);
} catch (Exception e) {
} finally {
try {
if (out != null) {
out.close();
}
} catch (IOException e) {
}
}
}
ImageUtils.java :
public static Set<String> getImgStr(String htmlStr) {
Set<String> pics = new HashSet<String>();
String img = "";
Pattern pImage;
Matcher mImage;
String regEx_img = "<img.*src\\s*=\\s*(.*?)[^>]*?>";
pImage = Pattern.compile(regEx_img, Pattern.CASE_INSENSITIVE);
mImage = pImage.matcher(htmlStr);
while (mImage.find()) {
// 得到<img />数据
img = mImage.group();
// 匹配<img>中的src数据 
Matcher m = Pattern.compile("src\\s*=\\s*\"?(.*?)(\"|>|\\s+)").matcher(img);
while (m.find()) {
pics.add(m.group(1));
}
}
return pics;
}
/**
* 下载图片
* @param urlString  路径
* @param filename   保存的文件名
* @param savePath   保存路径
*/
public static void download(String urlString, String filename, String savePath) {
InputStream is = null;
OutputStream os = null;
try {
File researchFile = new File(savePath + File.separator + filename);
if (researchFile.exists()) {
return;
}
// 构造URL
URL url = new URL(urlString);
// 打开连接
URLConnection con = url.openConnection(new Proxy();
// 设置请求超时为5s
con.setConnectTimeout(5*1000);
con.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)"); 
// 输入流
is = con.getInputStream();
// 1K的数据缓冲
byte[] bs = new byte[1024 * 1024 * 3];
// 读取到的数据长度
int len;
// 输出的文件流
File sf=new File(savePath);
if(!sf.exists()){
sf.mkdirs();
}
os = new FileOutputStream(sf.getPath() + File.separator + filename);
// 开始读取
while ((len = is.read(bs)) != -1) {
os.write(bs, 0, len);
}
// 完毕,关闭所有链接
os.close();
is.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (os != null) {
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

4. 总结

方法一断网无法显示图片,方法二linux下无法生成,方法三图片大小不易调整;但总体来说方法三优于前两者。如有错误还请指正,谢谢。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/182704.html原文链接:https://javaforall.cn

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022年10月12日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • HTML转word
  • 背景介绍
    • 1. 使用POI进行转化
      • 1.1 思路
      • 1.2 代码示例
      • 1.3 思考
    • 2. 使用jacob进行转化
      • 2.1 思路
      • 2.2 代码示例
      • 2.3 思考
    • 3. 使用itext进行转化
      • 3.1 思路
      • 3.2 代码示例
    • 4. 总结
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档