欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

如何使用Java將word解析出來(lái)(包含格式和圖片)

 更新時(shí)間:2023年12月23日 10:35:18   作者:未婚男子王某  
今天遇到一個(gè)讀取word模板內(nèi)容的需求,下面這篇文章主要給大家介紹了關(guān)于如何使用Java將word解析出來(lái),包含格式和圖片,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下

1、需求:

a. 將word中的內(nèi)容按照層級(jí)結(jié)構(gòu)解析出來(lái)

b. 不區(qū)分文件的后綴

c. 包含word的樣式

2、思路:

總體思路分為存和取,存的是文檔的標(biāo)題和內(nèi)容、圖片等;取的是文檔的樹形結(jié)構(gòu)。

        (1). 存:將word中的標(biāo)題、內(nèi)容、圖片獲取出來(lái)并進(jìn)行存儲(chǔ)

                a. 上傳文檔時(shí),獲取到文檔的名稱,存儲(chǔ)到數(shù)據(jù)庫(kù)表中,產(chǎn)生一個(gè)id,即documentId

                b. 解析word之后,按照順序遍歷獲取每一個(gè)標(biāo)題進(jìn)行存儲(chǔ),父標(biāo)題和子標(biāo)題之間使用parentId進(jìn)行關(guān)聯(lián),即子標(biāo)題中字段parentId是父標(biāo)題的id

                c. 在所有的標(biāo)題中都添加一個(gè)documentId方便后期范圍查詢

                d. 根節(jié)點(diǎn)即一級(jí)標(biāo)題的父id為0

                e. 查到的內(nèi)容如果是p標(biāo)簽,則與自己的上一級(jí)進(jìn)行關(guān)聯(lián),即p標(biāo)簽的父id為它的上一級(jí)標(biāo)簽id

                f. 關(guān)聯(lián)完成之后,生成一個(gè)樹形結(jié)構(gòu),并遍歷存儲(chǔ)到第三方平臺(tái)的數(shù)據(jù)庫(kù)中。

        (2). ?。焊鶕?jù)documentId查詢?cè)撐臋n的樹形結(jié)構(gòu)并返回

                a. 根據(jù)documentId查詢?cè)撐臋n的所有標(biāo)題并存儲(chǔ)到集合中去

                b. 對(duì)集合進(jìn)行遍歷,為了充分使用遞歸,規(guī)定最頂層的標(biāo)題的父節(jié)點(diǎn)為0,從父節(jié)點(diǎn)為0的元素開始遞歸,并將產(chǎn)生的結(jié)果生成樹形結(jié)構(gòu)并返回。

3、注意:

        (1). 因?yàn)樽约鹤龅闹饕窃诘谌狡脚_(tái)上的操作,所以類似于DmeTestRequestUtil.getDmeResult() 這樣的方法主要是跟第三方平臺(tái)的交互,出于安全性考慮就不放出來(lái)了。

         (2). 包含word的樣式:要思考的時(shí)怎么才能夠獲得word的樣式,即獲得html文件

         (3). 在解析的過(guò)程中樣式是以行內(nèi)式還是其他的效果呈現(xiàn):可以轉(zhuǎn)換為行內(nèi)式

         (4). 為什么不用poi:使用poi最惡心的是要考慮word的版本問(wèn)題

         (5). 使用的依賴主要是什么:aspose、jsoup

         (6). 層級(jí)結(jié)構(gòu)解析主要是判斷h、p的順序關(guān)系

4、代碼:

(1). 依賴

<dependency>
    <groupId>org.jsoup</groupId>
    <artifactId>jsoup</artifactId>
    <version>1.11.2</version>
</dependency>
<dependency>
    <groupId>com.aspose</groupId>
    <artifactId>aspose-words</artifactId>
    <version>15.8.0</version>
</dependency>

 (2). 解析word并保到第三方接口中代碼邏輯

/**
     * 解析word
     * @param multipartFile 前端接收的文件,根據(jù)自己的需求也可以將MultipartFile轉(zhuǎn)換為File
     * @return TitleTreeVO 存放標(biāo)題的實(shí)體
     * @author WangKuo
     * @date 2023/7/27 11:01
     */
public TitleTreeVO wordAnalysis(MultipartFile multipartFile) throws IOException {
        byte[] byteArr = multipartFile.getBytes();
        InputStream inputStream = new ByteArrayInputStream(byteArr);
        List<DocumentContentVO> documentContentVOList = new LinkedList<>();
        TitleTreeVO titleTreeVO = new TitleTreeVO();
        try {
            // 把流轉(zhuǎn)化為Document
            com.aspose.words.Document doc = new com.aspose.words.Document(inputStream);
            // 設(shè)置轉(zhuǎn)化的格式,HtmlSaveOptions轉(zhuǎn)換為HTML格式
            HtmlSaveOptions saveOptions = new HtmlSaveOptions();
            saveOptions.setExportImagesAsBase64(false);
            // 將所有word中的圖片放在臨時(shí)文件夾中,并將html中的鏈接替換為臨時(shí)文件夾中絕對(duì)路徑
            String property = System.getProperty("java.io.tmpdir");
            saveOptions.setImagesFolder(property);
            org.apache.commons.io.output.ByteArrayOutputStream baos = new ByteArrayOutputStream();
            doc.save(baos, saveOptions);
            String token = DmeTestRequestUtil.getToken();
            // 將html文件轉(zhuǎn)化為Document,方便后續(xù)使用jsoup的操作
            org.jsoup.nodes.Document htmlDoc = Jsoup.parse(baos.toString());
            // 設(shè)置html里面的圖片src路徑
            this.setImagePath(htmlDoc, token);
            // 存儲(chǔ)word文檔的名稱
            String substring = multipartFile.getOriginalFilename().substring(0, multipartFile.getOriginalFilename().lastIndexOf("."));
            JSONObject docParam = this.getDocParam(substring);
            String saveDocUrl = "https://dme.cn-south-4.huaweicloud.com/rdm_hwdmeverify_app/publicservices/api/DocumentSave/create";
            // 首先根據(jù)文檔名稱生成一條document的數(shù)據(jù),產(chǎn)生的id將在標(biāo)題實(shí)體中進(jìn)行關(guān)聯(lián)
            String dmeResult = DmeTestRequestUtil.getDmeResult(saveDocUrl, docParam, token);
            JSONObject jsonObject1 = JSONObject.parseObject(dmeResult);
            List data1 = jsonObject1.getObject("data", List.class);
            JSONObject jsonObjectData1 = (JSONObject) data1.get(0);
            String id = jsonObjectData1.getString("id");//文檔id
            // 存儲(chǔ)文檔的第一個(gè)標(biāo)題的返回結(jié)果,其中包含該節(jié)點(diǎn)的id和title
            documentContentVOList = this.exactContentFromHtml(htmlDoc);
            this.dmeSave(documentContentVOList, id, "0", token);//第一個(gè)標(biāo)題的父ID默認(rèn)為0
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            inputStream.close();
        }
        return titleTreeVO;
    }

/**
  	 * 在解析為html文件的時(shí)候需要將圖片的地址進(jìn)行一個(gè)替換,由最初的臨時(shí)文件地址替換為圖片在服務(wù)器上的位置
     * 設(shè)置圖片的路徑(src)
     * @param document 轉(zhuǎn)換為HTML的文檔內(nèi)容
     * @return void
     * @author Wangkuo
     * @date 2023/7/25 21:40
     */
    private void setImagePath(Document document) throws IOException {
        Elements imgs = document.select("img");
        String token = DmeTestRequestUtil.getToken();
        for (Element img : imgs) {
          	// 獲取出html中src內(nèi)的地址值
            String src = img.attr("src");
          	// 通過(guò)地址查到對(duì)應(yīng)的文件
            File file = new File(src);
            FileInputStream input = new FileInputStream(file);
          	// 將file轉(zhuǎn)化為MultipartFile
						MultipartFile multipartFile =new MockMultipartFile("file", file.getName(), "text/plain", IOUtils.toByteArray(input));
            // 該部分主要是第三方接口設(shè)置的必須傳的參數(shù),在這里我就先設(shè)置為定值,因?yàn)檫@些不干擾我的需求結(jié)果
						FormVo formVo = new FormVo();
            formVo.setAttributeName("File");
            formVo.setModelName("Document");
            formVo.setApplicationId("-1");
            String uploadImgUrl = "圖片作為文件,進(jìn)行上傳";
            String uploadImage = DmeTestRequestUtil.getDmeResultUploadFile(uploadImgUrl, multipartFile, formVo, token);
            JSONObject uploadImgJs = JSONObject.parseObject(uploadImage);
            List data = uploadImgJs.getObject("data", List.class);
          	// 上傳完成后,第三方接口會(huì)返回一個(gè)文件的id,我可以根據(jù)這個(gè)id進(jìn)行文件的預(yù)覽和下載
            String id = (String) data.get(0);
            //上傳文件file 并返回上傳的路徑;將路徑拼接出來(lái),并替換到html的document中
            String imgPath = "/api/dme-library/LibraryFolder/preview?fileId="+id;
            img.attr("src",imgPath);
						input.close();
          	// 刪除臨時(shí)文件夾中存儲(chǔ)的文件
            file.deleteOnExit();
        }
    }

/**
     * 該部分主要是第三方接口在調(diào)用時(shí)規(guī)定該接口的參數(shù)格式
     * 拼接參數(shù)
     * @param name 
     * @return com.alibaba.fastjson.JSONObject
     * @author Wangkuo
     * @date 2023/7/27 11:23
     */
    private JSONObject getDocParam(String name) {
        Map<String, Object> mapStr = new HashMap<>();
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("name", name);
        mapStr.put("params", paramMap);
        JSONObject jsonObject = new JSONObject(mapStr);
        return jsonObject;
    }

/**
     * 處理樹形結(jié)構(gòu)
     * @param htmlDoc 
     * @return java.util.List<DocumentContentVO>
     * @author Wangkuo
     * @date 2023/7/27 11:26
     */
    private List<DocumentContentVO> exactContentFromHtml(Document htmlDoc) throws Exception {
        Elements eleList = htmlDoc.getElementsByTag("h1");
        if (eleList == null || eleList.size() == 0) {
            throw new Exception("上傳的文件中不存在一級(jí)標(biāo)題,請(qǐng)檢查!");
        }

        Element hElement = htmlDoc.selectFirst("h1");//從第一個(gè)標(biāo)題1 開始往下找
        //Elements pElement = htmlDoc.select("h1");
        List<DocumentContentVO> allTreeList = new ArrayList<>();
        List<DocumentContentVO> list2 = new ArrayList<>();
        List<DocumentContentVO> list3 = new ArrayList<>();
        List<DocumentContentVO> list4 = new ArrayList<>();
        DocumentContentVO b1Map = new DocumentContentVO();
        DocumentContentVO b2Map = new DocumentContentVO();
        DocumentContentVO b3Map = new DocumentContentVO();
        DocumentContentVO b4Map = new DocumentContentVO();
        DocumentContentVO bMap = b1Map;//記錄當(dāng)前map
        //先將第一個(gè)標(biāo)題 放入
        int i = 1;
        b1Map.setTitle(hElement.toString());
        b1Map.setIndex(i);
        allTreeList.add(b1Map);
        while (hElement.nextElementSibling() != null) { //如果存在下一個(gè)標(biāo)題
            i++;
            hElement = hElement.nextElementSibling();
            String nodeName = hElement.nodeName();
            String s = hElement.tagName();
            //System.out.println(s);
            if (Objects.equals(nodeName, "h1")) {
                b1Map = new DocumentContentVO();
                bMap = b1Map;
                b1Map.setTitle(hElement.toString());
                b1Map.setIndex(i);
                allTreeList.add(b1Map);
                list2 = new ArrayList<>();
            } else if (Objects.equals(nodeName, "h2")) {
                b2Map = new DocumentContentVO();
                bMap = b2Map;
                list3 = new ArrayList<>();
                b2Map.setTitle(hElement.toString());
                b2Map.setIndex(i);
                list2.add(b2Map);
                b1Map.setChildList(list2);
            } else if (Objects.equals(nodeName, "h3")) {
                b3Map = new DocumentContentVO();
                bMap = b3Map;
                b3Map.setTitle(hElement.toString());
                b3Map.setIndex(i);
                list3.add(b3Map);
                b2Map.setChildList(list3);
            } else if (Objects.equals(nodeName, "h4")) {
                b4Map = new DocumentContentVO();
                bMap = b4Map;
                b4Map.setTitle(hElement.toString());
                b4Map.setIndex(i);
                list4.add(b4Map);
                b3Map.setChildList(list4);
            } else {
                bMap.setContent(bMap.getContent() == null ? hElement.toString() : bMap.getContent() + hElement.toString());
            }
        }
        return allTreeList;
    }

/**
     * 傳入html解析的樹 和對(duì)應(yīng)文檔id 通過(guò)遞歸實(shí)現(xiàn)保存
     *
     * @param treeList
     * @param id
     * @param parentId
     * @return java.lang.String
     * @author Wangkuo
     * @date 2023/7/25 16:48
     */
    private String dmeSave(List<DocumentContentVO> treeList, String id, String parentId,String token) {
        String dmeResult = null;
        for (DocumentContentVO documentContentVO : treeList) {
            if (documentContentVO != null) {
                String title = documentContentVO.getTitle();
                int sort = documentContentVO.getIndex();
                String content = documentContentVO.getContent();
                String url = "創(chuàng)建對(duì)應(yīng)數(shù)據(jù)的第三方url";
                JSONObject jsonObjectParam = this.paramJoint1(title, id, parentId, sort, content);
                dmeResult = DmeTestRequestUtil.getDmeResult(url, jsonObjectParam, token);
                List data = JSONObject.parseObject(dmeResult).getObject("data", List.class);
                if (data != null && !data.isEmpty()) {
                    JSONObject jsonObject = (JSONObject) data.get(0);
                    String parentIdNext = jsonObject.getString("id");
                    if (documentContentVO.getChildList() != null && documentContentVO.getChildList().size() > 0) {
                        dmeSave(documentContentVO.getChildList(), id, parentIdNext,token);
                    }
                }
            }
        }
        return dmeResult;
    }

/**
     * 同理,第三方接口規(guī)定的參數(shù)樣式,需要進(jìn)行拼接
     * @param title
     * @param id
     * @param parentId
     * @param sort
     * @param content 
     * @return com.alibaba.fastjson.JSONObject
     * @author Wangkuo
     * @date 2023/7/27 11:30
     */
    private JSONObject paramJoint1(String title, String id, String parentId, int sort, String content) {
        Map<String, Object> mapStr = new HashMap<>();
        Map<String, Object> paramsMap = new HashMap<>();
        if (id != null) {
            paramsMap.put("title", title);
            paramsMap.put("sort", sort);
            paramsMap.put("parentId", parentId);
            paramsMap.put("content", content);
            paramsMap.put("documentId", id);
        } else {
            paramsMap.put("title", title);
        }
        mapStr.put("params", paramsMap);
        return JSONObject.parseObject(JSON.toJSONString(mapStr));
    }

(3). 根據(jù)documentId查詢該篇文檔的標(biāo)題內(nèi)容樹形結(jié)構(gòu)

/**
 * 根據(jù)documentId查詢對(duì)應(yīng)的word文檔的樹形結(jié)構(gòu)
 * @param reqJSON {"id":"525663360008593408"}
 * @return java.util.List<TitleTreeVO>
 * @author Wangkuo
 * @date 2023/7/27 11:32
 */
public List<TitleTreeVO> getTreeCon(JSONObject reqJSON) {
    String id = reqJSON.getString("id");
    List<TitleTreeVO> allTitleByDocId = this.getAllTitleByDocId(id);
    TitleTreeVO titleTreeVO = new TitleTreeVO();
    titleTreeVO.setId("0");
    this.getChild(titleTreeVO,allTitleByDocId);
    return titleTreeVO.getChildList();
}

/**
     * 根據(jù)文檔id獲取到該文檔的所有標(biāo)題(此時(shí)獲取的集合沒(méi)有父子級(jí)關(guān)系)
     * @param docId 
     * @return java.util.List<TitleTreeVO>
     * @author Wangkuo
     * @date 2023/7/27 11:34
     */
    private List<TitleTreeVO> getAllTitleByDocId(String docId) {
        String url = "第三方標(biāo)題表的查詢";
				// 參數(shù)拼接
        JSONObject docIdParam = getDocIdParam(docId);
        String token = DmeTestRequestUtil.getToken();
        String dmeResult = DmeTestRequestUtil.getDmeResult(url, docIdParam, token);
        JSONObject jsonObject = JSONObject.parseObject(dmeResult);
        List data = jsonObject.getObject("data", List.class);
        List<TitleTreeVO> titleList = new ArrayList<>();
        if (data != null && !data.isEmpty()) {
            for (Object title : data) {
                JSONObject titleJson = (JSONObject)title;
                TitleTreeVO titleTreeVO = new TitleTreeVO();
                titleTreeVO.setContent(titleJson.getString("content"));
                titleTreeVO.setTitle(titleJson.getString("title"));
                titleTreeVO.setId(titleJson.getString("id"));
                titleTreeVO.setIndex(Integer.parseInt(titleJson.getString("sort")));
                titleTreeVO.setDocumentId(titleJson.getString("documentId"));
                titleTreeVO.setParentId(titleJson.getString("parentId"));
                titleList.add(titleTreeVO);
            }
        }
        return titleList;
    }

/**
     * 通過(guò)遞歸獲取到各級(jí)的子標(biāo)題和內(nèi)容
     * @param parentTitleTreeVO
     * @param titleListOld
     * @return TitleTreeVO
     * @author Wangkuo
     * @date 2023/7/27 11:42
     */
    private TitleTreeVO getChild(TitleTreeVO parentTitleTreeVO,List<TitleTreeVO> titleListOld) {
        List<TitleTreeVO> titleList = new ArrayList<>();
        if (titleListOld != null && titleListOld.size()>0) {
            List<TitleTreeVO> titleCollect = titleListOld.stream().filter(e -> e.getParentId().equals(parentTitleTreeVO.getId())).collect(Collectors.toList());
            if(titleCollect.size()>0){
                for (TitleTreeVO title : titleCollect) {
                    TitleTreeVO titleTreeVO = new TitleTreeVO();
                    titleTreeVO.setIndex(title.getIndex());
                    titleTreeVO.setTitle(title.getTitle());
                    titleTreeVO.setId(title.getId());
                    titleTreeVO.setContent(title.getContent());
                    titleTreeVO.setDocumentId(title.getDocumentId());
                    titleTreeVO.setParentId(title.getParentId());
                    titleList.add(titleTreeVO);
                    this.getChild(titleTreeVO,titleListOld);
                }
            }
        }
        List<TitleTreeVO> titleSortList = titleList.stream().sorted(Comparator.comparing(TitleTreeVO::getIndex)).collect(Collectors.toList());
        parentTitleTreeVO.setChildList(titleSortList);
        return parentTitleTreeVO;
    }

總結(jié) 

到此這篇關(guān)于如何使用Java將word解析出來(lái)的文章就介紹到這了,更多相關(guān)Java解析word內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • spring hibernate實(shí)現(xiàn)動(dòng)態(tài)替換表名(分表)的方法

    spring hibernate實(shí)現(xiàn)動(dòng)態(tài)替換表名(分表)的方法

    下面小編就為大家?guī)?lái)一篇spring hibernate實(shí)現(xiàn)動(dòng)態(tài)替換表名(分表)的方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-08-08
  • Jenkins+maven持續(xù)集成的實(shí)現(xiàn)

    Jenkins+maven持續(xù)集成的實(shí)現(xiàn)

    這篇文章主要介紹了Jenkins+maven持續(xù)集成的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04
  • httpclient evict操作源碼解讀

    httpclient evict操作源碼解讀

    這篇文章主要為大家介紹了httpclient evict操作源碼解讀,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-10-10
  • Mybatis使用useGeneratedKeys獲取自增主鍵的方法

    Mybatis使用useGeneratedKeys獲取自增主鍵的方法

    這篇文章主要給大家介紹了關(guān)于Mybatis使用useGeneratedKeys獲取自增主鍵的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用Mybatis具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09
  • Springboot基于assembly的服務(wù)化打包方案及spring boot部署方式

    Springboot基于assembly的服務(wù)化打包方案及spring boot部署方式

    這篇文章主要介紹了Springboot基于assembly的服務(wù)化打包方案及springboot項(xiàng)目的幾種常見的部署方式,本文主要針對(duì)第二種部署方式提供一種更加友好的打包方案,需要的朋友可以參考下
    2017-12-12
  • java線程之Happens before規(guī)則案例詳解

    java線程之Happens before規(guī)則案例詳解

    這篇文章主要為大家介紹了java線程之Happens-before規(guī)則,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪<BR>
    2022-08-08
  • Java字符串相關(guān)類操作方法詳解

    Java字符串相關(guān)類操作方法詳解

    這篇文章主要給大家介紹了關(guān)于Java字符串相關(guān)類操作的相關(guān)資料,文中還特別介紹了字符串的定義、構(gòu)造方法、內(nèi)存原理、比較方法和常見方法,同時(shí)還介紹了StringBuilder和StringJoiner類,需要的朋友可以參考下
    2024-12-12
  • 生產(chǎn)者消費(fèi)者模型ThreadLocal原理及實(shí)例詳解

    生產(chǎn)者消費(fèi)者模型ThreadLocal原理及實(shí)例詳解

    這篇文章主要介紹了生產(chǎn)者消費(fèi)者模型ThreadLocal原理及實(shí)例詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-09-09
  • SpringBoot集成Redisson操作Redis的實(shí)現(xiàn)方法

    SpringBoot集成Redisson操作Redis的實(shí)現(xiàn)方法

    Redisson是一個(gè)用于Java的Redis客戶端,它提供了在分布式環(huán)境下操作Redis數(shù)據(jù)庫(kù)的簡(jiǎn)單、高效的方式,本文主要介紹了SpringBoot集成Redisson操作Redis的實(shí)現(xiàn)方法,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-03-03
  • 解決kafka:org.apache.kafka.common.errors.TimeoutException問(wèn)題

    解決kafka:org.apache.kafka.common.errors.TimeoutException問(wèn)題

    這篇文章主要介紹了解決kafka:org.apache.kafka.common.errors.TimeoutException問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-01-01

最新評(píng)論