简介:本资源是iText 7 for .NET的完整开源SDK分发包,面向C#/.NET平台PDF开发工程师,解决PDF生成、编辑、数字签名、合规归档等企业级文档处理需求。包内含kernel.dll(底层PDF操作)、io.dll(I/O核心)、layout.dll(高级布局渲染)、forms.dll(AcroForm表单支持)、pdfa.dll(PDF/A长期存档)、sign.dll(PAdES数字签名与GDPR/CCPA合规支持)、barcode.dll(条形码嵌入)及font-asian.dll(中日韩文字渲染)等关键组件,覆盖PDF生成、安全加密、无障碍访问(PDF/UA)、电子签章、SVG转PDF、XFDF数据交换等全链路能力。压缩包为ZIP格式,共793.65MB,文件总数未统计但结构完整,适合作为项目依赖直接集成或SDK源码级学习参考。已有1504人学习下载,开发者可直接获取开箱即用的强类型.NET库、符合ISO标准的PDF处理能力及配套测试工具(pdftest.dll),显著降低PDF模块开发门槛与合规风险。
1. iText 7 for .NET:别急着 NuGet Install-Package iText7,先看清这三版兼容性玄学
去年帮某高校实验室迁移一个 PDF 批量归档系统时,开发同学信誓旦旦说“iTextSharp 换成 iText7 就是改个引用”,结果编译通过、运行时报System.MissingMethodException—— 不是代码写错了,是他在 .NET Framework 4.6.1 上装了 iText7 v8.0.0(仅支持 .NET 6+)。这种翻车不是个例:iText7 for .NET 从 v7.2.x 到 v8.x,底层运行时约束、PDF/A 支持粒度、数字签名 API 设计全变了。它不是“iTextSharp 的升级包”,而是一套重写的 SDK 级 PDF 引擎,专为现代 .NET 生态(.NET Core / .NET 5+)设计,同时反向兼容部分旧框架——但必须手动选对版本。如果你正卡在“PDF 生成失败”“数字签名验签报错”“PDF/A 验证不通过”或“AcroForm 字段读取为空”,大概率不是代码问题,而是环境没对齐。本文聚焦真实部署场景:用最小依赖、最稳版本组合,把 iText7 落地到 .NET Framework 4.7.2、.NET 5、.NET 6 三类主流环境,覆盖 PDF 生成、表单填充、PAdES 签名、PDF/A-2b 归档、SVG 转 PDF 等高频刚需。所有命令、配置、验证步骤均经实机复现,拒绝“理论上可行”。
2. 下载与版本选择:认准 iText7 v7.2.5(LTS)与 v8.0.3(.NET 6+ 优选)双轨策略
iText7 for .NET 不是单一包,而是一组强耦合的 NuGet 包族。盲目Install-Package iText7会默认拉取最新版(当前 v8.0.3),但它不兼容 .NET Framework 项目。必须根据目标框架精准选型。官方已明确:v7.x 是最后一个支持 .NET Framework 的长期支持(LTS)分支;v8.x 起仅支持 .NET Standard 2.1+,即最低要求 .NET Core 3.1 或 .NET 5+。这不是营销话术,是编译器层面的 ABI 兼容断层。
2.1 三类环境对应的核心包版本矩阵
| 目标运行时 | 推荐 iText7 主版本 | 关键 NuGet 包(含版本) | 说明 |
|---|---|---|---|
| .NET Framework 4.7.2+ | v7.2.5(LTS) | itext7 7.2.5itext7.pdfa 7.2.5itext7.signatures 7.2.5itext7.forms 7.2.5 | 官方声明的最后一个 .NET Framework 兼容版,含完整 PDF/A-2b、PAdES-BES、AcroForm 支持,无运行时异常风险 |
| .NET 5 / .NET 6 | v8.0.3(最新) | itext7 8.0.3itext7.pdfa 8.0.3itext7.signatures 8.0.3itext7.forms 8.0.3itext7.svg 8.0.3 | 原生支持 .NET 5+ 的 Span 、Memory ,SVG 渲染性能提升 40%,PAdES-LTV 签名链验证更严格,但移除了对 .NET Framework 的任何适配逻辑 |
| .NET Core 3.1 | v7.2.5 | 同上 .NET Framework 行 | v8.x 不支持 .NET Core 3.1(因缺少某些 API),强行安装会编译失败 |
提示:不要混用 v7.x 和 v8.x 的包。例如在 .NET 6 项目中安装
itext7 7.2.5+itext7.svg 8.0.3,会导致TypeLoadException—— 因为 v8 的SvgConverter依赖 v8 的PdfDocument内部结构,而 v7 的PdfDocument已重构。
2.2 下载方式:NuGet.org 官方源 + 离线包缓存(防网络抖动)
所有包均发布于 NuGet.org 官方仓库 ,严禁使用 GitHub Release 页面的 ZIP 源码包直接引用——那只是 SDK 示例,不含编译好的 .NET 程序集。正确操作是:
# 方式一:Visual Studio 包管理器控制台(推荐) # 对于 .NET Framework 项目(目标框架:.NET Framework 4.7.2) Install-Package itext7 -Version 7.2.5 Install-Package itext7.pdfa -Version 7.2.5 Install-Package itext7.signatures -Version 7.2.5 Install-Package itext7.forms -Version 7.2.5 # 对于 .NET 6 项目(目标框架:net6.0) Install-Package itext7 -Version 8.0.3 Install-Package itext7.pdfa -Version 8.0.3 Install-Package itext7.signatures -Version 8.0.3 Install-Package itext7.forms -Version 8.0.3 Install-Package itext7.svg -Version 8.0.3<!-- 方式二:.csproj 文件内显式声明(更可控,推荐团队协作) --> <!-- .NET Framework 项目示例 --> <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFramework>net472</TargetFramework> </PropertyGroup> <ItemGroup> <PackageReference Include="itext7" Version="7.2.5" /> <PackageReference Include="itext7.pdfa" Version="7.2.5" /> <PackageReference Include="itext7.signatures" Version="7.2.5" /> <PackageReference Include="itext7.forms" Version="7.2.5" /> </ItemGroup> </Project><!-- .NET 6 项目示例 --> <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFramework>net6.0</TargetFramework> </PropertyGroup> <ItemGroup> <PackageReference Include="itext7" Version="8.0.3" /> <PackageReference Include="itext7.pdfa" Version="8.0.3" /> <PackageReference Include="itext7.signatures" Version="8.0.3" /> <PackageReference Include="itext7.forms" Version="8.0.3" /> <PackageReference Include="itext7.svg" Version="8.0.3" /> </ItemGroup> </Project>逻辑说明:
itext7是核心引擎包,提供PdfWriter、PdfDocument等基础类;itext7.pdfa实现 PDF/A-1a/2b/3b 验证与生成;itext7.signatures封装 PAdES(ETSI EN 319 142)、CAdES 签名协议;itext7.forms处理 AcroForm 字段读写与 XFA 表单;itext7.svg是 v8 新增的独立模块,将 SVG XML 字符串渲染为 PDF 页面。v7.x 中 SVG 功能集成在itext7主包内,v8.x 拆分为独立包以降低主包体积。
2.3 离线包预下载:避免 CI/CD 构建时网络超时
在企业内网或 CI 服务器上,建议提前下载所有依赖包并推送到私有 NuGet 源(如 Azure Artifacts、ProGet)。若无私有源,可本地缓存:
# 使用 nuget.exe CLI(需提前下载 nuget.exe v6.8+) nuget install itext7 -Version 7.2.5 -OutputDirectory ./nuget-cache nuget install itext7.pdfa -Version 7.2.5 -OutputDirectory ./nuget-cache # ... 其他包同理然后在 Visual Studio 中添加本地源:
- 工具 → 选项 → NuGet 包管理器 → 包源 → + 号 → 名称填
Local-iText7,源填./nuget-cache路径 - 在包管理器中切换源为
Local-iText7,再执行Install-Package
这样即使构建机断网,也能秒级还原环境。
3. 基础环境配置:.NET 运行时、证书存储与字体路径三要素
装完 NuGet 包只是开始。iText7 的 PDF/A 归档、数字签名、中文字体渲染三大功能,严重依赖操作系统级配置。很多“生成 PDF 失败”报错,根源不在 C# 代码,而在 Windows 证书存储未初始化、或 Linux 字体路径未注册。
3.1 .NET 运行时版本校验(Windows / Linux / macOS 通用)
iText7 v7.2.5 要求最低 .NET Framework 4.7.2(Windows)或 .NET Core 2.1 Runtime(跨平台);v8.0.3 要求 .NET 6 Runtime。必须在目标机器上验证运行时存在,而非仅开发机有:
# Windows PowerShell:检查 .NET Framework 版本 (Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full').Release # 返回 461814 = .NET Framework 4.7.2;461808 = 4.7.1(不够!需升级)# Linux/macOS:检查 .NET SDK/Runtime dotnet --list-sdks dotnet --list-runtimes # 输出应包含: # Microsoft.NETCore.App 6.0.25 [/usr/share/dotnet/shared/Microsoft.NETCore.App] # 若无,则需下载 .NET 6 Runtime:https://dotnet.microsoft.com/download/dotnet/6.0参数说明:
.NET Framework 4.7.2的 Registry Release 值是硬编码的,不能靠Environment.Version获取;dotnet --list-runtimes显示的是已安装的共享运行时,比dotnet --version(显示 SDK 版本)更能反映实际执行环境。
3.2 Windows 证书存储初始化(数字签名必备)
iText7 的signatures模块在 Windows 上默认使用X509Store(StoreName.My, StoreLocation.CurrentUser)读取证书。但新用户首次登录时,CurrentUser\My存储区可能为空或未初始化,导致X509Store.Open()抛CryptographicException: The system cannot find the file specified。
血泪经验:不要在代码里 try-catch 这个异常然后忽略——它意味着签名根本不会执行。必须前置初始化:
// 在应用启动时(如 Program.cs Main() 开头)执行 using (var store = new X509Store(StoreName.My, StoreLocation.CurrentUser)) { try { store.Open(OpenFlags.ReadOnly); Console.WriteLine("证书存储初始化成功"); } catch (CryptographicException ex) when (ex.HResult == unchecked((int)0x80070002)) { // 文件未找到错误:强制创建空存储(需管理员权限) Console.WriteLine("证书存储未初始化,尝试修复..."); store.Open(OpenFlags.ReadWrite); // 此行会自动创建存储区 store.Close(); Console.WriteLine("证书存储已创建"); } }逻辑说明:
OpenFlags.ReadWrite在存储区不存在时会触发系统创建,但需要进程有写入HKEY_CURRENT_USER\Software\Microsoft\SystemCertificates\My\Certificates的权限。若应用以受限用户运行,此操作会失败,此时必须由管理员预先运行一次该初始化代码。
3.3 字体路径注册(中英文 PDF 生成不乱码)
iText7 默认只识别 Windows 的C:\Windows\Fonts和 Linux 的/usr/share/fonts。但中文 PDF 常需自定义字体(如 Noto Sans CJK、思源黑体)。v7.x 与 v8.x 的字体注册 API 不同:
// iText7 v7.2.5:使用 FontProgramFactory FontProgram fontProgram = FontProgramFactory.CreateFont(@"C:\fonts\NotoSansCJKsc-Regular.otf"); FontConstants.Register(fontProgram, "NotoSansCJKsc"); // iText7 v8.0.3:FontProgramFactory 已废弃,改用 FontProvider FontProvider provider = new FontProvider(); provider.AddFont(@"C:\fonts\NotoSansCJKsc-Regular.otf"); // 使用时:new PdfFont(provider.GetFont("NotoSansCJKsc", true))关键参数:
AddFont(string path)的path必须是绝对路径;相对路径(如"./fonts/xxx.ttf")在 IIS 或 Linux systemd 服务中会解析失败。我一般会在应用启动时校验字体文件是否存在:
string fontPath = Path.Combine(AppContext.BaseDirectory, "fonts", "NotoSansCJKsc-Regular.otf"); if (!File.Exists(fontPath)) throw new FileNotFoundException($"字体文件缺失: {fontPath}");4. 核心功能落地:PDF 生成、表单填充、PAdES 签名、PDF/A 归档四步实操
本章给出四个生产环境高频场景的最小可运行代码,全部基于上文选定的版本(v7.2.5 或 v8.0.3),每段代码均可直接复制进Program.cs运行。重点标注版本差异点与安全参数。
4.1 基础 PDF 生成(含 SVG 渲染)
// iText7 v8.0.3(.NET 6+)示例:SVG 转 PDF using iText.Kernel.Pdf; using iText.Layout.Document; using iText.Layout.Element; using iText.Svg.Processors; // 创建 PDF using var writer = new PdfWriter("output.pdf"); using var pdf = new PdfDocument(writer); var doc = new Document(pdf); // 渲染 SVG 字符串(注意:v7.x 不支持此 API,需用 XML 解析后手动画) string svgXml = @"<svg width='200' height='100'><rect x='10' y='10' width='180' height='80' fill='#4CAF50'/><text x='20' y='50' font-family='Arial' font-size='14'>Hello SVG</text></svg>"; var svgElement = SvgConverter.FromXml(svgXml, new ConverterProperties()); doc.Add(svgElement); doc.Close(); Console.WriteLine("PDF 生成完成");// iText7 v7.2.5(.NET Framework)示例:纯文本 PDF using iText.Kernel.Pdf; using iText.Layout.Document; using iText.Layout.Element; using var writer = new PdfWriter("output_v7.pdf"); using var pdf = new PdfDocument(writer); var doc = new Document(pdf); // 注册中文字体(v7.x) FontProgram font = FontProgramFactory.CreateFont(@"C:\fonts\NotoSansCJKsc-Regular.otf"); FontConstants.Register(font, "NotoSansCJKsc"); // 添加带中文字体的段落 var para = new Paragraph("这是中文测试") .SetFont(FontConstants.GetFont("NotoSansCJKsc")); doc.Add(para); doc.Close();参数说明:
SvgConverter.FromXml()是 v8.0.3 新增的高阶 API,内部自动处理坐标系、CSS 样式继承;v7.x 需用XmlWorkerHelper(已废弃)或手动解析 SVG DOM。FontConstants.Register()在 v7.x 中是静态方法,v8.x 中已移除,必须用FontProvider实例。
4.2 AcroForm 表单字段填充(动态 PDF)
// 通用代码(v7.2.5 & v8.0.3 均适用) using iText.Kernel.Pdf; using iText.Forms.Fields; // 打开已有 PDF 表单(需含 AcroForm 字段) using var reader = new PdfReader("form_template.pdf"); using var writer = new PdfWriter("filled_form.pdf"); using var pdf = new PdfDocument(reader, writer); // 获取表单 var form = PdfAcroForm.GetAcroForm(pdf, true); // 填充字段(字段名需与 PDF 中完全一致,区分大小写) form.GetField("name").SetValue("张三"); form.GetField("email").SetValue("zhangsan@example.com"); form.GetField("date").SetValue(DateTime.Now.ToString("yyyy-MM-dd")); // 必须调用 flattenFields() 才能导出为不可编辑 PDF(否则字段仍可修改) form.FlattenFields(); pdf.Close(); Console.WriteLine("表单填充完成");逻辑说明:
PdfAcroForm.GetAcroForm(pdf, true)的true参数表示“如果 PDF 无 AcroForm 则自动创建”,但实际中应确保模板 PDF 已含有效字段。FlattenFields()是关键——它将字段值渲染为普通文本,移除交互能力,满足归档合规要求(如 GDPR 数据最小化)。
4.3 PAdES-BES 数字签名(符合 ETSI EN 319 142)
// iText7 v7.2.5 / v8.0.3 均适用(API 一致) using iText.Signatures; using iText.Kernel.Pdf; using System.Security.Cryptography.X509Certificates; // 加载证书(PFX 文件,含私钥) var cert = new X509Certificate2(@"C:\certs\signer.pfx", "password", X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet); // 创建签名外观(v7/v8 参数名相同) PdfSigner signer = new PdfSigner( new PdfReader("unsigned.pdf"), new FileStream("signed.pdf", FileMode.Create), new StampingProperties().UseAppendMode()); // UseAppendMode() 保留原 PDF 结构,符合 PAdES // 设置签名属性 IExternalSignature pks = new PrivateKeySignature( cert.GetRSAPrivateKey(), // .NET Core 3.1+ / .NET 5+ 用 GetRSAPrivateKey() DigestAlgorithms.SHA256); ICryptoStandard cryptoStandard = CryptoStandard.CMS; // PAdES-BES 使用 CMS 标准 // 执行签名 signer.SignDetached(pks, cert, null, null, null, 0, cryptoStandard); Console.WriteLine("PAdES-BES 签名完成");安全参数:
DigestAlgorithms.SHA256是当前合规底线,SHA1 已被禁用;CryptoStandard.CMS对应 PAdES-BES(Basic Electronic Signature),若需 PAdES-LTV(Long Term Validation),需额外调用signer.SetCertificationLevel(PdfSigner.CERTIFIED_FORM_FILLING_AND_ANNOTATIONS)并嵌入 OCSP 响应。
4.4 PDF/A-2b 归档合规生成(GDPR / CCPA 合规关键)
// iText7 v7.2.5 / v8.0.3 均适用(需引用 itext7.pdfa 包) using iText.Kernel.Pdf; using iText.Layout.Document; using iText.Pdfa; // 创建 PDF/A-2b 文档 var writer = new PdfAWriter("archive.pdf", new PdfADocument.PdfAConformanceLevel.PDF_A_2B()); // 注意:v7.x 用 PdfAConformanceLevel.PDF_A_2B,v8.x 同名 var pdf = new PdfADocument(writer, PdfAConformanceLevel.PDF_A_2B, new PdfOutputIntent("Custom", "", "http://www.color.org", "sRGB IEC61966-2.1", new FileStream(@"C:\icc\sRGB.icc", FileMode.Open))); // 必须嵌入 ICC 配置文件 var doc = new Document(pdf); // 添加内容(必须使用嵌入字体) var font = FontProgramFactory.CreateFont(@"C:\fonts\NotoSansCJKsc-Regular.otf"); doc.Add(new Paragraph("归档文档正文").SetFont(font)); doc.Close(); Console.WriteLine("PDF/A-2b 归档生成完成");合规要点:PDF/A-2b 要求所有字体必须嵌入(
SetFont()时字体必须是FontProgram实例,不能用系统字体名)、必须嵌入 ICC 配置文件(sRGB.icc 是公开标准文件,可从 https://www.color.org/srgbprofiles.xalter 下载)、禁止透明度、音频、视频等非静态元素。PdfAWriter构造函数中的PdfAConformanceLevel.PDF_A_2B是硬性开关,设错则生成无效 PDF/A。
5. 避坑指南:五个真实踩过的坑与后悔药
部署 iText7 最痛苦的不是写代码,而是那些不报错却让功能静默失效的“黑匣子”问题。以下是我在三个不同客户现场亲手填平的坑,按现象→原因→解决三步法整理,每一条都附带验证命令。
5.1 现象:PDF/A 验证失败,报 “Missing output intent”
原因:创建PdfADocument时未传入PdfOutputIntent,或 ICC 文件路径错误导致加载失败(但 iText7 不抛异常,静默降级为非 PDF/A)。
解决:
- 确保 ICC 文件存在且可读:
ls -l /usr/share/color/icc/colord/sRGB.icc(Linux)或dir C:\icc\sRGB.icc(Windows) - 在代码中强制校验 ICC 加载:
var iccStream = new FileStream(@"C:\icc\sRGB.icc", FileMode.Open); var outputIntent = new PdfOutputIntent("Custom", "", "http://www.color.org", "sRGB IEC61966-2.1", iccStream); // 验证:outputIntent.GetOutputStream() != null5.2 现象:数字签名后 Adobe Acrobat 显示 “签名有效性未知”
原因:证书链不完整。iText7 默认只嵌入签名证书,不嵌入中间 CA 证书,导致验证端无法构建信任链。
解决:手动添加证书链:
var chain = new List<X509Certificate>(); chain.Add(cert); // 签名证书 chain.Add(intermediateCaCert); // 中间 CA(从证书颁发机构获取) chain.Add(rootCaCert); // 根 CA(通常已预装,但嵌入更稳妥) signer.SignDetached(pks, chain.ToArray(), null, null, null, 0, cryptoStandard);5.3 现象:.NET 6 项目中itext7.svg渲染 SVG 报NullReferenceException
原因:v8.0.3 的SvgConverter依赖System.Drawing.Common,但 .NET 6 默认不启用 GDI+(Linux/macOS 无 GDI)。
解决:在.csproj中添加:
<PropertyGroup> <EnableUnsafeBinaryFormatterInDeserialization>true</EnableUnsafeBinaryFormatterInDeserialization> <!-- 关键:启用 System.Drawing --> <UseWpf>false</UseWpf> <UseWindowsForms>false</UseWindowsForms> </PropertyGroup> <ItemGroup> <PackageReference Include="System.Drawing.Common" Version="6.0.0" /> </ItemGroup>并在 Linux 上安装 libgdiplus:apt-get install libgdiplus。
5.4 现象:AcroForm 字段填充后中文显示为方框
原因:字体注册路径错误,或 PDF 模板本身未设置字段的默认字体(/DA属性为空)。
解决:
- 检查模板字段默认字体:用
pdfinfo -meta template.pdf查看是否含AcroForm字段信息 - 强制为字段设置字体:
var field = form.GetField("name"); field.SetValue("张三"); field.SetWidgetFontAndSize(font, 12); // v7.2.5;v8.0.3 用 field.SetDefaultAppearance("0 0 0 rg /NotoSansCJKsc 12 Tf");5.5 现象:Install-Package itext7.pdfa编译失败,提示 “The type or namespace name 'PdfAConformanceLevel' could not be found”
原因:未同时安装itext7主包,或版本不匹配(如itext7.pdfa 8.0.3与itext7 7.2.5混用)。
解决:
- 卸载所有 iText 包:
Uninstall-Package itext7 -Force(PowerShell) - 清理 NuGet 缓存:
dotnet nuget locals all --clear - 重新安装同一版本号的全套包(见 2.1 矩阵表)
- 重启 Visual Studio(VS 有时缓存旧元数据)
6. 验证跑通:用四条命令确认你的 iText7 环境真正可用
装完不验证,等于没装。我给自己定的铁律是:每次部署新环境,必须跑通以下四个验证点,缺一不可。它们覆盖了 PDF 生成、合规性、安全性、可访问性四大维度,比单纯“能输出 Hello World”可靠十倍。
6.1 验证 1:基础 PDF 生成与字体嵌入(防乱码)
# Windows / Linux 均可用 # 步骤:运行生成 PDF 的代码 → 用 pdfinfo 检查字体 pdfinfo -fonthist output.pdf | grep -i "NotoSansCJK" # 期望输出:NotoSansCJKsc-Regular 12.0 0 embedded # 若输出 "not embedded" 或找不到字体名,则字体注册失败6.2 验证 2:PDF/A-2b 合规性(GDPR 归档硬指标)
# 使用开源工具 veraPDF(权威 PDF/A 验证器) # 下载地址:https://verapdf.org/download/ verapdf --format text --policy ./src/test/resources/metadata/policy/PDF_A-2B.xml output.pdf # 期望输出:最后三行是 # PASSED: 1 # FAILED: 0 # NOT_APPLICABLE: 0 # 若出现 "FAILED: 1" 且错误为 "OutputIntent is missing",则 ICC 未嵌入6.3 验证 3:数字签名可被 Adobe Acrobat 验证(PAdES 合规)
# 手动验证:用 Adobe Acrobat Reader DC(免费版)打开 signed.pdf # 点击右上角“签名”面板 → 查看签名属性 → 确认: # - 签名者:显示证书 CN 名(如 "CN=Zhang San") # - 签名时间:与代码中 `DateTime.Now` 一致 # - 状态:显示绿色对勾 + "签名有效"(非“未知”) # - 详细信息 → 证书路径:显示完整三级链(End Entity → Intermediate CA → Root CA)6.4 验证 4:AcroForm 字段可被第三方工具读取(无障碍与互操作)
# 使用 pdftk(PDF Toolkit)提取表单字段 pdftk filled_form.pdf dump_data_fields # 期望输出包含: # --- # FieldType: Text # FieldName: name # FieldValue: 张三 # FieldFlags: 0 # 若 FieldValue 为空或显示乱码,则表单填充未生效或字体问题从那以后我每次给客户交付 PDF 系统,都强制走一遍这四条命令验证。不是信不过自己的代码,而是信不过环境——.NET 运行时版本、证书存储状态、字体路径、ICC 文件权限,任何一个环节松动,都会让 PDF 在某个角落静默失效。而用户只会说“你们的系统坏了”,不会说“你们的 ICC 文件没读权限”。希望帮到你。
本文还有配套的精品资源,点击获取