狂自私

导航

Excel-xlsx文件从底层入手添加水印

水印,本质上是一个背景图像;

昨天研发(java)那边在研究如何给xlsx文件添加水印,但是试了几个库,easyexcel啥的,都不行,有个商业库倒是支持,但是很明显不能采用。

然后我想着之前研究xlsx底层xml的历程,想着在底层进行添加水印,经过几轮测试,得到了我想要的结果,特此记录下来。

一、解压xlsx文件

xlsx文件本质上是一个zip压缩包,所以第一步是先把数据扔里面去,通过标准的接口生成一个xlsx文件,然后解压出来,目录结构大体如下:

PS 2025年6月25日 13:26:40 C:\Users\Administrator> tree.com 水印测试-手动编辑底层 /F
卷 新加卷 的文件夹 PATH 列表
卷序列号为 E60B-B1BE
水印测试-手动编辑底层
│  [Content_Types].xml
│
├─docProps
│      app.xml
│      core.xml
│
├─xl
│  │  styles.xml
│  │  workbook.xml
│  │
│  ├─media
│  │      image1.png
│  │
│  ├─printerSettings
│  │      printerSettings1.bin
│  │
│  ├─theme
│  │      theme1.xml
│  │
│  ├─worksheets
│  │  │  sheet1.xml
│  │  │
│  │  └─_rels
│  │          sheet1.xml.rels
│  │
│  └─_rels
│          workbook.xml.rels
│
└─_rels
        .rels

PS 2025年6月25日 13:26:44 C:\Users\Administrator>

我们要关注的文件:

[Content_Types].xml

xl\worksheets\_rels\sheet1.xml.rels

xl\worksheets\sheet1.xml #这里我只有一个sheet页,若是有多个,切都需要添加水印,那么就都需要关注。 

二、最重要的内容

[Content_Types].xml文件

这个文件内容里面列举了xlsx文件有哪些资源:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">
    <Default Extension="bin" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.printerSettings"/>
    <Default Extension="png" ContentType="image/png"/>
    <Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/>
    <Default Extension="xml" ContentType="application/xml"/>
    <Override PartName="/xl/workbook.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml"/>
    <Override PartName="/xl/worksheets/sheet1.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"/>
    <Override PartName="/xl/theme/theme1.xml" ContentType="application/vnd.openxmlformats-officedocument.theme+xml"/>
    <Override PartName="/xl/styles.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml"/>
    <Override PartName="/docProps/core.xml" ContentType="application/vnd.openxmlformats-package.core-properties+xml"/>
    <Override PartName="/docProps/app.xml" ContentType="application/vnd.openxmlformats-officedocument.extended-properties+xml"/>
</Types>

重要的是这个:<Default Extension="png" ContentType="image/png"/>

声明有png图片资源

若是不声明,Excel会报错,选择修复之后会忽略掉png资源。

xl\worksheets\_rels\sheet1.xml.rels文件

这个文件声明了一些二进制资源:

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

注意看,请记住Id值,后面有用。

xl\worksheets\sheet1.xml文件

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="x14ac xr xr2 xr3" xmlns:x14ac="http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac" xmlns:xr="http://schemas.microsoft.com/office/spreadsheetml/2014/revision" xmlns:xr2="http://schemas.microsoft.com/office/spreadsheetml/2015/revision2" xmlns:xr3="http://schemas.microsoft.com/office/spreadsheetml/2016/revision3" xr:uid="{7BB1DCAF-490D-4A01-8426-55D136EFAA68}">
    <dimension ref="F11"/>
    <sheetViews>
        <sheetView showGridLines="0" tabSelected="1" workbookViewId="0">
            <selection activeCell="J22" sqref="J22"/>
        </sheetView>
    </sheetViews>
    <sheetFormatPr defaultRowHeight="14.25" x14ac:dyDescent="0.2"/>
    <cols>
        <col min="6" max="6" width="10.5" bestFit="1" customWidth="1"/>
    </cols>
    <sheetData>
        <row r="11" spans="6:6" x14ac:dyDescent="0.2">
            <c r="F11" s="1"/>
        </row>
    </sheetData>
    <phoneticPr fontId="1" type="noConversion"/>
    <pageMargins left="0.7" right="0.7" top="0.75" bottom="0.75" header="0.3" footer="0.3"/>
    <pageSetup paperSize="9" orientation="portrait" r:id="rId1"/>
    <picture r:id="rId2"/>
</worksheet>

需要注意的是最后的<picture r:id="rId2"/>。这个r:id引用的rId2就是xl\_rels\workbook.xml.rels文件文件中的id,对应id指向的资源。

压缩

把几个文件内容改好保存后,就需要进行压缩了。

这里有两个注意的点:

压缩的目录层级

我们需要在[Content_Types].xml文件所在的目录下对应相关文件进行压缩,而不是在[Content_Types].xml文件的父目录进行压缩:

这样压缩是对的:

 

 这样压缩就是错误的:

 压缩完之后,改下zip后缀为xlsx即可。

posted on 2025-06-25 14:21  狂自私  阅读(38)  评论(0)    收藏  举报