整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

java后端实现word上传并转html格式

近有一个业务是前端要上传word格式的文稿,然后用户上传完之后,可以用浏览器直接查看该文稿,并且可以在富文本框直接引用该文稿,所以上传word文稿之后,后端保存到db的必须是html格式才行,所以涉及到word格式转html格式。

通过调查,这个word和html的处理,有两种方案,方案1是前端做这个转换。方案2是把word文档上传给后台,后台转换好之后再返回给前端。至于方案1,看到大家的反馈都说很多问题,所以就没采用前端转的方案,最终决定是后端转化为html格式并返回给前段预览,待客户预览的时候,确认格式没问题之后,再把html保存到后台(因为word涉及到的格式太多,比如图片,visio图,表格,图片等等之类的复杂元素,转html的时候,可能会很多格式问题,所以要有个预览的过程)。

对于word中普通的文字,问题倒不大,主要是文本之外的元素的处理,比如图片,视频,表格等。针对我本次的文章,只处理了图片,处理的方式是:后台从word中找出图片(当然引入的jar包已经带了获取word中图片的功能),上传到服务器,拿到绝对路径之后,放入到html里面,这样,返回给前端的html内容,就可以直接预览了。


maven引入相关依赖包如下:

 <poi-scratchpad.version>3.14</poi-scratchpad.version>
        <poi-ooxml.version>3.14</poi-ooxml.version>
        <xdocreport.version>1.0.6</xdocreport.version>
        <poi-ooxml-schemas.version>3.14</poi-ooxml-schemas.version>
        <ooxml-schemas.version>1.3</ooxml-schemas.version>
        <jsoup.version>1.11.3</jsoup.version>


<dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-scratchpad</artifactId>
            <version>${poi-scratchpad.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>${poi-ooxml.version}</version>
        </dependency>
        <dependency>
            <groupId>fr.opensagres.xdocreport</groupId>
            <artifactId>xdocreport</artifactId>
            <version>${xdocreport.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml-schemas</artifactId>
            <version>${poi-ooxml-schemas.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>ooxml-schemas</artifactId>
            <version>${ooxml-schemas.version}</version>
        </dependency>
        <dependency>
            <groupId>org.jsoup</groupId>
            <artifactId>jsoup</artifactId>
            <version>${jsoup.version}</version>
        </dependency>

word转html,对于word2003和word2007转换方式不一样,因为word2003和word2007的格式不一样,工具类如下:

使用方法如下:

public String uploadSourceNews(MultipartFile file)  {
        String fileName = file.getOriginalFilename();
        String suffixName = fileName.substring(fileName.lastIndexOf("."));
        if (!".doc".equals(suffixName) && !".docx".equals(suffixName)) {
            throw new UploadFileFormatException();
        }
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMM");
        String dateDir = formatter.format(LocalDate.now());
        String directory = imageDir + "/" + dateDir + "/";
        String content = null;
        try {
            InputStream inputStream = file.getInputStream();
            if ("doc".equals(suffixName)) {
                content = wordToHtmlUtil.Word2003ToHtml(inputStream, imageBucket, directory, Constants.HTTPS_PREFIX + imageVisitHost);
            } else {
                content = wordToHtmlUtil.Word2007ToHtml(inputStream, imageBucket, directory, Constants.HTTPS_PREFIX + imageVisitHost);
            }
        } catch (Exception ex) {
            logger.error("word to html exception, detail:", ex);
            return null;
        }
        return content;
    }

关于doc和docx的一些存储格式介绍:

docx 是微软开发的基于 xml 的文字处理文件。docx 文件与 doc 文件不同, 因为 docx 文件将数据存储在单独的压缩文件和文件夹中。早期版本的 microsoft office (早于 office 2007) 不支持 docx 文件, 因为 docx 是基于 xml 的, 早期版本将 doc 文件另存为单个二进制文件。

DOCX is an XML based word processing file developed by Microsoft. DOCX files are different than DOC files as DOCX files store data in separate compressed files and folders. Earlier versions of Microsoft Office (earlier than Office 2007) do not support DOCX files because DOCX is XML based where the earlier versions save DOC file as a single binary file.


可能你会问了,明明是docx结尾的文档,怎么成了xml格式了?

很简单:你随便选择一个docx文件,右键使用压缩工具打开,就能得到一个这样的目录结构:


所以你以为docx是一个完整的文档,其实它只是一个压缩文件。


参考:

https://www.cnblogs.com/ct-csu/p/8178932.html

了编写一个Java爬虫,你需要了解以下几个步骤:

  1. 首先,你需要确定你要抓取的网站。可以从浏览器中复制网站的URL并粘贴到你的Java代码中。
  2. 接下来,你需要使用Java的网络编程API连接到该网站。你可以使用URLConnection或HttpClient等库。
  3. 一旦你建立了一个连接,你就可以开始读取网页内容。你可以使用Java的IO库读取网页。
  4. 在读取网页内容之后,你需要解析网页以提取所需的信息。这可以使用Java的解析器,如Jsoup或XML解析器。
  5. 最后,你需要存储或使用所提取的信息。你可以将信息保存到数据库中,将其输出到文件中,或将其用于其他用途。

下面是一个基本的Java爬虫代码示例,它使用Jsoup解析器和URLConnection库连接到目标网站并提取标题和链接信息:

import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.util.Scanner;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

public class SimpleWebCrawler {
  
  public static void main(String[] args) {
    String url = "https://www.example.com/";
    try {
      URLConnection conn = new URL(url).openConnection();
      conn.addRequestProperty("User-Agent", "Mozilla/5.0");
      Scanner scanner = new Scanner(conn.getInputStream());
      String html = scanner.useDelimiter("\\Z").next();
      scanner.close();
      Document doc = Jsoup.parse(html);
      Elements links = doc.select("a[href]");
      for (Element link : links) {
        System.out.println(link.attr("href") + " - " + link.text());
      }
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}

Jsoup

Jsoup是一款用于解析HTML和XML文档的Java库。它提供了类似于jQuery的语法来操作文档,使得解析和处理文档变得非常简单。

以下是Jsoup解析器的一些常用功能:

  1. 解析HTML文档:使用Jsoup可以轻松解析HTML文档,并且可以处理各种标签、属性、文本内容等。
  2. 获取元素:可以使用类似于jQuery的选择器语法来获取HTML文档中的元素,例如获取所有的链接、图片等。
  3. 修改元素:可以使用Jsoup修改HTML文档中的元素,例如修改元素的属性、添加或删除元素等。
  4. 过滤HTML文档:可以使用Jsoup过滤HTML文档中的不必要的元素,例如过滤掉广告、统计代码等。
  5. 处理字符编码:可以使用Jsoup来处理HTML文档中的字符编码,例如将文档中的ISO-8859-1编码转换为UTF-8编码等。
  6. 支持HTTPS:Jsoup还支持使用HTTPS协议获取HTML文档,可以使用它来爬取一些需要登录才能访问的网站。

总之,Jsoup是一款非常实用的HTML和XML解析器,可以帮助Java开发者快速、简单地解析和处理HTML文档,使得爬虫开发变得更加容易。

Jsoup的使用

使用Jsoup解析器需要先将其添加到项目的依赖中。可以通过Maven或者Gradle来添加依赖。

例如,使用Maven添加Jsoup的依赖:

<dependency>
    <groupId>org.jsoup</groupId>
    <artifactId>jsoup</artifactId>
    <version>1.14.3</version>
</dependency>

添加依赖之后,就可以在Java代码中使用Jsoup了。以下是使用Jsoup解析器获取HTML文档中所有链接的示例代码:

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

public class JsoupExample {
    public static void main(String[] args) {
        String html = "<html><head><title>Jsoup Example</title></head>"
                + "<body><p>Jsoup is a Java library for working with real-world HTML.</p>"
                + "<a href=\"http://example.com\">Example</a></body></html>";

        Document doc = Jsoup.parse(html); // 将HTML字符串解析为文档对象

        Elements links = doc.select("a"); // 获取所有的链接元素

        for (Element link : links) {
            String href = link.attr("href"); // 获取链接的URL地址
            String text = link.text(); // 获取链接的文本内容
            System.out.println(href + ": " + text);
        }
    }
}

以上代码使用Jsoup将HTML字符串解析为文档对象,然后使用选择器语法获取所有的链接元素,并输出它们的URL地址和文本内容。

除此之外,Jsoup还有很多其他的功能,例如修改元素、过滤HTML文档等等,可以根据具体需求灵活运用。

Jsoup 解析器的常见功能和代码片段示例

1.获取网页的 Title:

Document doc = Jsoup.connect("http://example.com/").get();
String title = doc.title();

2.获取指定标签的文本内容:

Element element = doc.select("div.content").first();
String text = element.text();

3.获取指定属性的值:

Element element = doc.select("img").first();
String src = element.attr("src");

4.过滤 HTML 标签:

String html = "<p>这是一段 <b>加粗</b> 的文本。</p>";
String text = Jsoup.parse(html).text();

5.修改 HTML 内容:

Element element = doc.select("div.content").first();
element.append("<p>这是新增的文本内容。</p>");

6.提取网页中的链接:

Elements links = doc.select("a[href]");
for (Element link : links) {
    String href = link.attr("href");
    System.out.println(href);
}

7.提取网页中的图片:

Elements imgs = doc.select("img[src~=(?i)\\.(png|jpe?g|gif)]");
for (Element img : imgs) {
    String src = img.attr("src");
    System.out.println(src);
}

这些只是 Jsoup 解析器的常见用法之一。Jsoup 还有更多的功能,如解析 XML、处理表单、处理 Cookie 等,大家可以自己去了解!

有不足之处大家也可以在评论区指出!

近在工作中遇到一个bug,将word转换成html,转换成功之后在浏览器中打开其中图片不显示,使用img标签,src指定图片相对地址又是能显示的,排除图片问题。

网上能搜索到的demo

打开转码之后的html代码发现,生成的是vml图片标签,这个在IE9以后就不支持了,更别说现在的主流浏览器了。

生成的html中使用的是vml标签

将这个跟大佬分析分析,各种文档一查,咔咔咔大致分析出问题所在。原来jacob使用的是word本身自带的功能,相当于把word打开另存为html,于是手动将word转为html试了一下,果然效果与代码转换一致,这时候注意到word另存为时有一个web选项,里面有个使用vml渲染图片默认是选中的,去掉这个选项,再次生成,图片正常显示。



到这里基本已经确定了问题的解决思路,另存为时不勾选这个选项,那么问题来了,怎么利用jacob操作另存为时去掉这个选项呢,想去搜搜看jacob相关的文档,结果不知道是不是因为这个很老了,网上大多数都是demo,根本没有相关的文档可看,Github上也是只言片语,根本无从查起。

jacob github 地址:https://github.com/joval/jacob

微软官网文档

官方文档连接:https://docs.microsoft.com/zh-cn/office/vba/api/word.weboptions.relyonvml

微软官网查询相关文档,发现其实是可以关闭的,于是代码变成这样

关闭relyOnVml

再次运行程序,这次转出来的html就能在浏览器打开了。

总结,在这次解决问题的过程中,学会了往更深层次去想问题,找对方向,迎难而上。

记录一下这个问题解决的经验,也希望能帮到同样遇到这个问题的人。