1. 程式人生 > >Word-docx檔案圖片資訊格式分析

Word-docx檔案圖片資訊格式分析

現在新需求來了,匯出的Word文件中、需要包含圖片。

大致的處理流程為:

  1. 解析匯出資訊、將 <img ... src="xxx" ...> 抽取出來。 替換為 [img[xxxIdInt]];
  2. 替換 HTML 標籤
  3. [img[xxxIdInt]] 格式的字串、使用XML標籤替換回去。 參考下面的程式碼段。
  4. 下載 src 為 byte[];
  5. 處理為物件;
  6. 處理對應的 XML 文件,生成 String 和 byte[]
  7. 替換 docx/zip 檔案的某些 entry, 加上圖片的 entry.

相關原始碼

圖片部分的XML大致如下:

public static String template_t_start = "</w:t
>
</w:r><w:r>"; public static String template_t_end = "</w:r><w:r><w:t>"; public static String template_drawing = "<w:drawing>" + "<wp:inline>" + "<wp:extent cx=\"
{{imgWEMU}}\" cy=\"{{imgHEMU}}\"/>" + "<wp:docPr id=\"{{imgId}}\" name=\"圖片
{{imgId}}\"/>" + "<a:graphic xmlns:a=\"http://schemas.openxmlformats.org/drawingml/2006/main\">" + "<a:graphicData uri=\"http://schemas.openxmlformats.org/drawingml/2006/picture\">" + "<pic:pic xmlns:pic=\"http://schemas.openxmlformats.org/drawingml/2006/picture\">" + "<pic:nvPicPr
>
" + "<pic:cNvPr id=\"
{{imgId}}\" name=\"Picture {{imgId}}\"/>" + "<pic:cNvPicPr/>" + "</pic:nvPicPr>" + "<pic:blipFill>" + "<a:blip r:embed=\"rId{{imgId}}\"></a:blip>" + "<a:stretch><a:fillRect/></a:stretch>" + "</pic:blipFill>" + "<pic:spPr bwMode=\"auto\">" + "<a:xfrm><a:ext cx=\"{{imgWEMU}}\" cy=\"{{imgHEMU}}\"/></a:xfrm>" + "<a:prstGeom prst=\"rect\"><a:avLst/></a:prstGeom>" + "<a:noFill/><a:ln><a:noFill/></a:ln>" + "</pic:spPr>" + "</pic:pic>" + "</a:graphicData>" + "</a:graphic>" + "</wp:inline>" + "</w:drawing>"; public static String imgTemplate = template_t_start + template_drawing + template_t_end;

如果檔案版本不一致、請自己抽取 docx 檔案中的相關文件來對比。

圖片資訊模型如下:

public class WordImagePropertyVO {
    public static int emuWeight = 9525; // emu全職; EMU = 畫素*weight;

    private String imgId; // ID,如20,21,22
    private String relationshipId;
    private Integer width=0; // 圖片的寬度
    private Integer height=0;// 圖片的高度
    private Integer imgHEMU; // EMU = 畫素*weight;
    private Integer imgWEMU;
    private String imgSrc;
    private byte[] imgByte;
    ...
}

ZipUtils 類增加了一些方法:

/**
 * 自定義的ZIP工具
 */
public class ZipUtils {
    /**
     * 替換ZIP中的部分條目
     * @param zipInputStream 輸入zip流
     * @param zipOutputStream 寫出zip流
     * @param replaceItems 替換列表
     */
    public static void replaceItems(ZipInputStream zipInputStream,
                                   ZipOutputStream zipOutputStream,
                                 Map<String, InputStream> replaceItems
    ) {
        if (null == zipInputStream || null == zipOutputStream) {
            return;
        }
        if (null == replaceItems) {
            replaceItems = new HashMap<>();
        }
        ZipEntry entryIn;
        try {
            // 1. 替換
            while ((entryIn = zipInputStream.getNextEntry()) != null) {
                String entryName = entryIn.getName();
                //
                boolean shouldReplaceItem = replaceItems.containsKey(entryName);
                InputStream targetItemInputStream = replaceItems.get(entryName);
                //
                if(shouldReplaceItem && null == targetItemInputStream){
                    continue;// 需要刪除的item;
                }
                // 只使用 name
                ZipEntry entryOut = new ZipEntry(entryName);
                zipOutputStream.putNextEntry(entryOut);
                // 緩衝區
                byte[] buf = new byte[8 * 1024];
                int len;
                if (shouldReplaceItem) {
                    // 使用替換流
                    while ((len = (targetItemInputStream.read(buf))) > 0) {
                        zipOutputStream.write(buf, 0, len);
                    }
                } else {
                    // 輸出普通Zip流
                    while ((len = (zipInputStream.read(buf))) > 0) {
                        zipOutputStream.write(buf, 0, len);
                    }
                }
                // 關閉此 entry
                zipOutputStream.closeEntry();
            }
            // 2. 新增 items
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }
    // 新增 items
    public static void addItems(ZipInputStream zipInputStream,
                                    ZipOutputStream zipOutputStream,
                                    Map<String, InputStream> addItems
    ) {
        if (null == zipInputStream || null == zipOutputStream || null == addItems || addItems.isEmpty()) {
            return;
        }
        Set<String> itemKeys = addItems.keySet();
        // 2. 新增 items
        try {
            for(String entryName :itemKeys){
                //
                InputStream targetItemInputStream = addItems.get(entryName);
                //
                if(null == entryName || null == targetItemInputStream){
                    continue;
                }
                //
                ZipEntry entryOut = new ZipEntry(entryName);
                zipOutputStream.putNextEntry(entryOut);
                // 緩衝區
                byte[] buf = new byte[8 * 1024];
                int len;
                // 使用替換流
                while ((len = (targetItemInputStream.read(buf))) > 0) {
                    zipOutputStream.write(buf, 0, len);
                }
                // 關閉此 entry
                zipOutputStream.closeEntry();
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

1. 引入檔案格式:

根據需要增加, 如 pngjpeg

[Content_Types].xml 檔案中需要增加以下內容:

<Default Extension="png" ContentType="image/png"/>
<Default Extension="jpeg" ContentType="image/jpeg"/>

2. word/document.xml引入名稱空間:

此部分、可以將一個無圖的docx、一個有圖的docx、抽取相關xml檔案格式化後對比得出。

<w:document 
            ......
            xmlns:wp14="http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:wpc="http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas"
            xmlns:w14="http://schemas.microsoft.com/office/word/2010/wordml"
            xmlns:wpg="http://schemas.microsoft.com/office/word/2010/wordprocessingGroup"
            xmlns:wpi="http://schemas.microsoft.com/office/word/2010/wordprocessingInk"
            xmlns:wps="http://schemas.microsoft.com/office/word/2010/wordprocessingShape" mc:Ignorable="w14 wp14"
            >

圖片繪製元素w:drawing

<w:r>
    <w:drawing>
      ...
    </w:drawing>
</w:r>

w:drawing子元素: 行內元素(inline)

<w:drawing>
    <wp:inline distT="0" distB="0" distL="0" distR="0">
      ...
    </wp:inline>
</w:drawing>

其中 distT 之類的屬性是距離上方Text的間距。(Distance From Text on Top Edge)

wp:inline子元素:

<wp:inline distT="0" distB="0" distL="0" distR="0">

<wp:extent cx="5274310" cy="3620117"/>
<wp:effectExtent l="0" t="0" r="2540" b="0"/>
<wp:docPr id="20" name="圖片 20"/>
<wp:cNvGraphicFramePr>
    <a:graphicFrameLocks xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main"
 noChangeAspect="1"/>
</wp:cNvGraphicFramePr>
  ......
</wp:inline>

其中:

  • 必需元素: <wp:extent cx="5274310" cy="3620117"/> 是圖片的寬高= 畫素值*9525; 後面還有一個 <a:ext cx="5274310" cy="3620117"/> 與之對應。為什麼是9525我也不知道, 參考https://msdn.microsoft.com/en-us/library/ee342530(v=office.12).aspx
  • 非必需元素: <wp:effectExtent l="0" t="0" r="2540" b="0"/>,估計是用於控制特效之類的擴充套件屬性。
  • 必需元素: <wp:docPr id="20" name="圖片 20"/> ; 應該是圖片的文件屬性, 其中ID互相之間不重複即可。
  • 非必需元素: <wp:cNvGraphicFramePr>; 不可見元素的屬性。(Common DrawingML Non-Visual Properties)

wp:inline子元素<a:graphic>:

<wp:inline distT="0" distB="0" distL="0" distR="0">
  ......
   <a:graphic xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main">
     ...
   </a:graphic>
</wp:inline>

a:graphic單一子元素<a:graphicData>

<a:graphic xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main">
    <a:graphicData uri="http://schemas.openxmlformats.org/drawingml/2006/picture">
      ...
    </a:graphicData>
</a:graphic>
<a:graphicData> 子元素:
<a:graphicData uri="http://schemas.openxmlformats.org/drawingml/2006/picture">
    <pic:pic xmlns:pic="http://schemas.openxmlformats.org/drawingml/2006/picture">
      ...
    </pic:pic>
</a:graphicData>
pic:pic子元素列表:
<pic:pic xmlns:pic="http://schemas.openxmlformats.org/drawingml/2006/picture">
    <pic:nvPicPr>
        <pic:cNvPr id="20" name="Picture 20"/>
        <pic:cNvPicPr/>
    </pic:nvPicPr>
    <pic:blipFill>
      ...
    </pic:blipFill>
    <pic:spPr bwMode="auto">
      ...
    </pic:spPr>
</pic:pic>
必需元素: <pic:nvPicPr>:

表示 Non-Visual Picture Properties:

  • <pic:nvPicPr>
    • cNvPicPr 表示 (Non-Visual Picture Drawing Properties)
      • 非必需元素 a:picLocks, 指定生成程式的行為等。
    • cNvPr 表示(Non-Visual Drawing Properties),是必需元素, 其中ID互相之間不重複即可
必需元素: <pic:blipFill> :

Picture Fill, 如下所示:

<pic:blipFill>
  <a:blip r:embed="rId20">
  </a:blip>
  <a:srcRect/>
  <a:stretch>
    <a:fillRect/>
  </a:stretch>
</pic:blipFill>

其中, 重要元素是<a:blip r:embed="rId20">:

  • 重要屬性: embed (Embedded Picture Reference),表示嵌入的圖片引用。
    • 引用關係處於檔案: word/_rels/document.xml.rels 檔案中.
  • 重要子元素:<a:stretch> 控制縮放, <a:fillRect/> 表示填滿?

  • <a:extLst>擴充套件屬性列表, BlipExtensionList, 可以忽略

必需元素: <pic:spPr>

Shape Properties.

<pic:spPr bwMode="auto">
    <a:xfrm>
        <a:off x="0" y="0"/>
        <a:ext cx="5274310" cy="3620117"/>
    </a:xfrm>
    <a:prstGeom prst="rect">
        <a:avLst/>
    </a:prstGeom>
    <a:noFill/>
    <a:ln>
        <a:noFill/>
    </a:ln>
</pic:spPr>

其中:

  • bwMode 屬性(Black and White Mode)
  • <a:xfrm> - Transform2D, 屬性。
    • <a:off x="0" y="0"/> 表示 Offset; 有預設值可忽略。
    • 重要屬性: <a:ext cx="5274310" cy="3620117"/> 表示大小, 參考上文。

3. word/_rels/document.xml.rels檔案中存在對應的 Rid

形如:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Relationships
    xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
    ....
    <Relationship Id="rId20" 
        Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"
        Target="media/image20.png"/>
    ...
</Relationships>

可以看到, rId20 的關係。

4. 相關的media檔案:

word/media/image20.png

5. 注意事項:

  • 不能有&nbsp; ?

相關推薦

Word-docx檔案圖片資訊格式分析

現在新需求來了,匯出的Word文件中、需要包含圖片。 大致的處理流程為: 解析匯出資訊、將 <img ... src="xxx" ...> 抽取出來。 替換為 [img[xxxIdInt]]; 替換 HTML 標籤 將 [img[xxxId

Nodejs把接收圖片base64格式儲存為檔案儲存到伺服器上

下面一小段程式碼給大家分享Nodejs把接收圖片base64格式儲存為檔案儲存到伺服器上的方法,具體程式碼如下所示: 前端精品教程:百度網盤下載 ? 1

Word檔案格式轉換:Word如何轉換成PDF格式

Word檔案如何轉換成PDF格式呢? 可能大部分人都知道PDF轉換成word格式,畢竟這也是一種常用的轉換。就word轉換成PDF小編在這裡告訴大家一種方法! 1、首先我們需要藉助輔助工具進行檔案格式轉換,大家可以在百度瀏覽器上搜索迅捷PDF轉換器,安裝在我們所操作的電腦上。 2、滑鼠雙擊執行開啟PDF轉換

HTTP POST請求報文格式分析與Java實現檔案上傳

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

怎麼將一張CAD圖紙檔案轉換成一張圖片格式呢?

怎麼將一張CAD圖紙檔案轉換成一張圖片的格式呢?CAD格式的圖紙檔案都可以將其轉換成dwg或是其他一些格式的,有時候在我們拿到開啟一張CAD圖紙的時候需要將其轉換成圖片格式時候,我們應該如何進行操作呢?今天小編就要來教教大家怎麼將一張CAD圖紙檔案轉換成一張圖片格式的全部操作步驟了,希望大家進行採納! 第一

Linux逆向---ELF格式分析檔案頭和程式頭

在Linux下,可以利用vim編輯器來對編譯生成後的可執行程式進行編輯,比如說把75jne指令改成74je指令,這樣可以在不重新編譯的情況下去修改程式的控制流,這樣玩感覺還是很有意思的,不過也僅限於此,所以我借了一本書想要學學逆向。。結果發現這本書真的難啃。。如果只是讀它的內容的話很快就讀過

ArcGIS 切片快取緊湊檔案格式分析與使用

一、分析 在ArcGIS 10中出現了一種新的切片快取檔案格式:緊湊型儲存(Compact)。與之前的鬆散型儲存(Exploded)相比,它有遷移方便、建立更快、減少儲存空間等諸多優點,已經成為了建立切片快取的預設格式。對於本身ArcGIS的產品而言,訪問緊湊型儲存與訪問鬆

PDF格式分析(三十八)Thumbnail Images 縮圖圖片

PDF文件可以包含以微縮形式表示其頁面內容的縮圖影象。 符合PDF標準的閱讀器可以在螢幕上顯示這些影象,允許使用者通過單擊其縮圖影象導航到對應的頁面。(縮圖影象不是必需的,可能包含在某些頁面中而不是全部頁面。) 頁面的縮圖影象,位於頁面物件中Thumb條目指定

Linux ELF檔案格式分析---objcopy命令的使用

本文轉自:https://blog.csdn.net/xj178926426/article/details/73777611  Linux ELF檔案格式分析—objcopy命令的使用 最近在看《程式設計師的自我修養—連結、裝載與庫》一書,對書中提到的一個小問題,自己做了

mp4(H264容器)的詳細檔案格式分析

十六進位制碼流分析:ftyp Box00 00 00 1C:  size ,28,表示此BOX有28個位元組,表示長度的四個位元組也計算在內。以下同66 74 79 70:  type,表示BOX TYPE,此處為ftyp6D 70 34 32:  可能是相容的格式資訊,/////mp4200 00 00 0

hadoop 1.0.4 fsimage 檔案格式分析

2013-01-08 周海漢 2013.1.8 http://abloz.com/2013/01/08/hadoop-1-0-4-fsimage-file-format.html fsimage檔案存放在NameNode中,

windows下用Python把pdf檔案轉化為圖片(png格式)

最近工作中需要把pdf檔案轉化為圖片,想用python來實現,於是在網上找啊找啊找啊找,找了半天,倒是找到一些程式碼。 1、第一個找到的程式碼,我試了一下好像是反了,只能實現把圖片轉為pdf,而不能

VBA/VBScript提取Word(*.doc)檔案中包含的圖片(照片)

要處理的人事簡歷表是典型的Word文件,其中一人一份doc,裡面包含有個人的照片,如果要把裡面的照片複製出來就比較麻煩了,一般手動的做法是選擇檔案另存為,儲存型別選擇“網頁(*.htm; *.html)”,這樣就會另存為網頁形式,同時會有個以檔名開頭,以.files結尾的資料夾,點選進去就可以看到Word

分析flv檔案資訊

上一篇博文“FLV檔案格式解析”提到的小工具FLVParse,是由於工作需要,我自己寫的一個小程式。 這個工具的主要功能是檢視FLV的檔案結構,幫助我們理解FLV格式。另外,如果涉及到處理FLV檔案的開發,這個工具對於檢視處理結果非常有幫助。因此我覺得有必要寫一個使用說明,希望這個工具能夠給大家提供

趣探 Mach-O:檔案格式分析

本文所讀的原始碼,可以從這裡找到,這是 Mach-O 系列的第一篇 我們的程式想要跑起來,肯定它的可執行檔案格式要被作業系統所理解,比如 ELF 是 Linux下可執行檔案的格式,PE32/PE32+是windows的可執行檔案的格式,那麼對於OS X和iOS 來說 Mach-

入門級 PDF 檔案格式分析

一、概述:     結構化的文件格式PDF(Portable Document Format)是由美國排版與影象處理軟體公司Adobe於1993年首次提出的。Adobe Reader這款pdf閱讀器軟體相信大家並不陌生,人們熟知它的原因是因為它的應用相當普及,可能接觸過計

常見圖片格式分析

一.  影象的基本結構:1.    在計算機中, 影象是由一個個畫素點組成,畫素點就是顏色點,而顏色最簡單的方式就是用RGB或RGBA表示;2.    如果有A通道就表明這個影象可以有透明效果;R,G,B每個分量一般是用一個位元組(8位)來表示;3.    影象是二維資料,資

C#BMP檔案格式分析並讀取

原文地址:https://blog.csdn.net/guanchanghui/article/details/1172092 主要是方便自己用,複製了一下,建議大家看原文 簡介 BMP(Bitmap-File)圖形檔案是Windows採用的圖形檔案格式,在Windows環

VC++圖片控制元件(Picture Control)顯示資源點陣圖(BMP)、檔案點陣圖(BMP)、其它格式檔案圖片(JPG\PNG\BMP)的方法

在VC++ MFC程式設計中,我們常使用Picture Control圖片控制元件來顯示影象。下面簡單歸納幾種顯示不同的方式: 第一種、資源點陣圖方式顯示BMP圖片 如果要顯示的是一張BMP點陣圖,則可以採用資源點陣圖方式,具體步驟如下: (1)將BMP檔案拷貝到工程的r

UNIX/LINUX 平臺可執行檔案格式分析

    本文討論了 UNIX/LINUX 平臺下三種主要的可執行檔案格式:a.out(assembler and link editor output 彙編器和連結編輯器的輸出)、COFF(Common Object File Format 通用物件檔案格式)、ELF(Executable and Linki