我们很高兴宣布 GroupDocs.Merger for .NET v26.10 已于 2026年10月 发布。此版本引入了对外部资源加载的重大增强,解决了 EPUB 和 TeX 处理中的关键并发问题,改进了 EPUB 的分页,保留了自动标记输出中的 PDF 格式和标题,并修复了多个 .NET Framework 相关的失败。总体而言,包含 10 项功能、改进和错误修复。
本次发布的新内容
- [功能] 默认跳过加载外部资源,可使用受信任位置白名单和每个资源的处理程序进行控制
- [错误] 修复 EPUB 文档的目录文件没有 .ncx 扩展名时出现的 NullReferenceException
- [错误] 修复在 .NET Framework packages.config 项目中图像合并时无法加载 System.ValueTuple 的问题
- [错误] 修复在 .NET Framework 4.6.2 至 4.7.0 运行时合并 SVG 文档时的错误
- [错误] 将固定布局 EPUB 页面渲染为每本书一页,而不是每页拆分为两页
- [错误] 将 System.Security.Cryptography.Pkcs 更新至 8.0.2 和 9.0.21(CVE-2026-84008、CVE-2026-70162)
- [错误] 在启用自动标记时保存 PDF 时保留原始 PDF 格式和标题
- [错误] 修复并发加载 TeX 文档时出现的 ArgumentException
- [错误] 将仅提供文件名的 LowCode 输出保存到当前目录,并拒绝合并不同格式的文档
- [错误] 修复并发处理 EPUB 文档时间歇性出现的 NullReferenceException 或 IndexOutOfRangeException
公共 API 更改
1. 外部资源 — 默认拒绝(新 API,不向后兼容)
GroupDocs.Merger.Domain.Options 命名空间中的新公共类型:
| 类型 | 描述 |
|---|---|
| IResourceLoadingOptions | 定义 SkipExternalResources、WhitelistedResources 和 ExternalResourceHandler。LoadOptions 实现该接口。 |
| IExternalResourceHandler | 其 OnLoading 方法在每个外部资源加载前被调用,可允许、跳过或替换该资源。 |
| ExternalResourceLoadingArgs | 传递给 OnLoading 的资源:Uri、Skipped(预设为其他两个选项的决定)以及 Data(用于替代加载资源的内容)。 |
[LoadOptions](https://reference.groupdocs.com/merger/net/groupdocs.merger.domain.options/loadoptions/) 的新属性:
SkipExternalResources— 在每个构造函数中默认true。为true时,除匹配WhitelistedResources或由处理程序允许的资源外,所有外部资源均不加载。WhitelistedResources— 在SkipExternalResources为true时仍会加载的资源的绝对 URI 前缀,例如https://cdn.example.com/assets/或file:///C:/assets/。默认为空。ExternalResourceHandler— 默认null。
不向后兼容的更改:
- 外部资源默认不再加载。 远程资源(
http、https、ftp等协议)、UNC 路径、本地文件(包括文档自身文件夹中的文件)以及指向文档外部的相对引用都会被跳过,操作继续进行。早期版本会加载这些资源。因此 HTML、Word 和演示文稿的远程图片和样式表可能在输出中缺失,HTML 和 Word 文档的页数也可能变化。文档自身携带的内容——data:URI、cid:引用、MHTML 部分和打包媒体——仍会加载。要加载外部资源,请将其位置加入白名单,或将SkipExternalResources设置为false(仅对可信文档)。 LoadOptions现在是sealed。 继承自它的类将无法编译。请直接使用LoadOptions,或实现ILoadOptions;如果自定义的ILoadOptions实现未同时实现IResourceLoadingOptions,则使用默认策略。WhitelistedResources条目若为 null、空、不是绝对 URI、包含查询或片段,或包含%2F、%5C、%2E,Merger构造函数将抛出ArgumentException(“Whitelisted resource ‘…’ must be an absolute URI without a query, fragment or encoded ‘/’, ‘\’ or ‘.’.”)。- 如果处理程序抛异常,资源将被跳过,操作会抛出
GroupDocsMergerException(“The external resource handler threw an exception; the resource was skipped. See the inner exception.”),内部异常为处理程序的异常。 - EPUB 文档以及某些操作中的 SVG、SVGZ 文档现在会检查其标记中的外部引用。标记不是良好 XML 的文档将因
GroupDocsMergerException(“The document’s markup could not be read to check it for external resources, so it was not loaded. Set SkipExternalResources to false without an ExternalResourceHandler to load it without the check.”)而未被加载。 OleDiagramOptions、OleSpreadsheetOptions和OleWordProcessingOptions构造函数(接受文件路径和页码)在渲染嵌入对象的图像时会拒绝外部资源,无论目标文档的LoadOptions如何。若要显示它们,请使用接受图像数据的构造函数并自行提供图像。GroupDocs.Merger.LowCode包的产品始终拒绝外部资源。
这些选项在创建 Merger 时读取,随后加入的文档将遵循其选项。
2. 自动标记的 PDF 文档保留源文件的格式和标题
无 API 更改。使用 PdfSaveOptions.AccesibilitySettings.EnableAutoTagging 设置为 true 保存的 PDF 文档会保留 PDF 格式和源文件的标题。之前所有自动标记的文档都会被标记为 PDF/UA-1,且未命名的源会得到标题 “Tagged PDF”。自动标记会添加逻辑结构树,但不会使文档符合 PDF/UA 标准,已标记为 PDF/UA 的源文件仍保持其标记。
3. 固定布局 EPUB 文档 — 每本书一页
无 API 更改。固定布局 EPUB 文档现在每本书对应一页。之前每本书会被渲染为两页,导致 GetDocumentInfo 返回的页数是实际页数的两倍,页码 N 与书页 N 不匹配。现在传递给 ExtractPages、RemovePages、Split 等页面操作的页码均指向书页。
4. GroupDocs.Merger.LowCode — 输出路径和合并文档
JoinPdf、JoinDocx、JoinPptx和RemovePagesPdf会将相对输出路径解析为当前工作目录。仅提供文件名的输出路径现在保存到当前目录;之前会保存到 Merger 的默认输出目录。空或 null 的输出路径会抛出ArgumentNullException。JoinPdf、JoinDocx和JoinPptx在合并文档的扩展名与产品格式不匹配时会抛出FileTypeNotSupportedException,并在写入任何输出之前终止,例如 “Input format does not match the expected format ‘PDF’; the joined file ‘a.docx’ is ‘Microsoft Word Open XML Document (.docx)’.”。之前JoinPdf和JoinDocx会产生混合输出,JoinPptx则在后期抛出其他错误。空或 null 的合并文档路径会抛出ArgumentNullException(“The document at index 0 is null or empty.”)。- 所有七个产品在源路径没有扩展名时会抛出
FileTypeNotSupportedException(“Input format does not match the expected format ‘PDF’; the supplied file is ‘Unknown’.”),而不是ArgumentException。
5. 依赖项
- 运行时包依赖于 System.Security.Cryptography.Pkcs 8.0.2(
GroupDocs.Merger.Net60、GroupDocs.Merger.Net80及其.Windows包)或 9.0.21(GroupDocs.Merger.Net100和GroupDocs.Merger.Net100.Windows)。GroupDocs.Merger.Net60、GroupDocs.Merger.Net60.Windows和GroupDocs.Merger.LowCode还依赖于 System.Formats.Asn1 8.0.2,GroupDocs.Merger.LowCode依赖于 System.Security.Cryptography.Pkcs 8.0.2。GroupDocs.Merger.Net462未变。 - 在 .NET Framework 项目中,
GroupDocs.Merger包不再向app.config或web.config(packages.config 项目)添加 System.ValueTuple 的绑定重定向,其 .NET Framework 构建目标会将DependsOnNETStandard设置为true,除非项目自行设置。
新功能
- 外部资源控制: 远程图片、样式表、链接图片及文档引用的其他文件默认不加载,除非显式允许。
LoadOptions新增SkipExternalResources、WhitelistedResources和ExternalResourceHandler属性,可允许受信任位置、对可信文档全部放行,或在代码中自行决定、跳过或提供每个资源。 - 并发修复: EPUB 文档不再因
NullReferenceException或IndexOutOfRangeException间歇性失败,TeX 文档在多线程处理时也不再出现ArgumentException。 - EPUB 文档: 固定布局 EPUB 现在每本书对应一页,页码 N 与书页 N 对应;目录文件扩展名不是
.ncx的 EPUB 不再因NullReferenceException失败。 - 自动标记的 PDF 输出: 启用自动标记保存的 PDF 保留源文件的格式和标题。除非源本身是 PDF/UA,否则不再被标记为 PDF/UA-1,未命名源也不再得到标题 “Tagged PDF”。
- .NET Framework 项目: packages.config 项目中的图像合并不再因加载 System.ValueTuple 失败,合并 SVG 文档在 .NET Framework 4.6.2 至 4.7.0 运行时也不再因加载 netstandard 失败。
- 已修补的依赖项: 包依赖于 System.Security.Cryptography.Pkcs 8.0.2(.NET 6.0 与 .NET 8.0)或 9.0.21(.NET 10.0),这些版本修复了 CVE-2026-84008 和 CVE-2026-70162。
- LowCode 产品: 仅提供文件名的输出路径保存到当前目录,
JoinPdf、JoinDocx、JoinPptx在写入任何输出前会拒绝不同格式的合并文档。
代码示例
using System.Collections.Generic;
using GroupDocs.Merger;
using GroupDocs.Merger.Domain;
using GroupDocs.Merger.Domain.Options;
var loadOptions = new LoadOptions(FileType.HTML)
{
// Load resources from one trusted folder only; everything else stays denied
WhitelistedResources = new List<string> { "https://cdn.example.com/assets/" }
};
using (var merger = new Merger("page1.html", loadOptions))
{
merger.Join("page2.html");
merger.Save("merged.html");
}
using System;
using GroupDocs.Merger.Domain.Options;
public class TrustedPngHandler : IExternalResourceHandler
{
public void OnLoading(ExternalResourceLoadingArgs args)
{
Uri uri;
if (Uri.TryCreate(args.Uri, UriKind.Absolute, out uri)
&& uri.Scheme == Uri.UriSchemeHttps
&& uri.Host == "cdn.example.com"
&& uri.AbsolutePath.EndsWith(".png", StringComparison.OrdinalIgnoreCase))
{
args.Skipped = false; // allow; any other resource keeps the default decision
}
}
}
如何获取更新
NuGet
通过 NuGet 升级到最新的 GroupDocs.Merger 包:GroupDocs.Merger 26.10.0
dotnet add package GroupDocs.Merger --version 26.10.0
直接下载
从 GroupDocs.Merger for .NET 26.10 页面下载程序集。