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即可。
浙公网安备 33010602011771号