2023年如何用C# .NET将FlowDocument或XPS转换为PDF?
2023年FlowDocument/XPS转PDF的可行方案(避开Microsoft Print to PDF缺陷)
方案1:使用Ghostscript.NET(开源跨平台)
依赖安装
安装NuGet包:Ghostscript.NET
示例代码
using System.IO; using System.Collections.Generic; using System.Windows.Documents; using System.Windows.Xps.Packaging; using Ghostscript.NET.Rasterizer; public void ConvertFlowDocumentToPdf(FlowDocument flowDoc, string outputPdfPath) { // 将FlowDocument转换为XPS内存流 using var xpsStream = new MemoryStream(); using var package = Package.Open(xpsStream, FileMode.Create); using var xpsDoc = new XpsDocument(package); var xpsWriter = XpsDocument.CreateXpsDocumentWriter(xpsDoc); xpsWriter.Write(((IDocumentPaginatorSource)flowDoc).DocumentPaginator); xpsStream.Position = 0; // 调用Ghostscript转换XPS到PDF using var rasterizer = new GhostscriptRasterizer(); var gsArguments = new List<string> { "-dNOPAUSE", "-dBATCH", "-sDEVICE=pdfwrite", $"-sOutputFile={outputPdfPath}", "-f-" // 从标准输入读取XPS流 }; rasterizer.Open(xpsStream, GhostscriptVersionInfo.GetLastInstalledVersion(), gsArguments.ToArray()); }
说明
- 基于开源的Ghostscript引擎,支持复杂XPS文档的转换,跨平台兼容
- 需确保系统中已安装Ghostscript运行时,或使用带嵌入式运行时的NuGet变体(如
Ghostscript.NET.Core)
方案2:使用XpsToPdf(轻量开源库)
依赖安装
安装NuGet包:XpsToPdf
示例代码
using System.IO; using System.Windows.Documents; using System.Windows.Xps.Packaging; using XpsToPdf; public void FlowDocumentToPdf(FlowDocument flowDoc, string pdfOutputPath) { // 先将FlowDocument转为XPS内存流 using var xpsStream = new MemoryStream(); using var package = Package.Open(xpsStream, FileMode.Create); using var xpsDoc = new XpsDocument(package); var xpsWriter = XpsDocument.CreateXpsDocumentWriter(xpsDoc); xpsWriter.Write(((IDocumentPaginatorSource)flowDoc).DocumentPaginator); xpsStream.Position = 0; // 一键转换XPS到PDF XpsConverter.Convert(xpsStream, pdfOutputPath); }
说明
- 专为XPS转PDF场景设计,API简洁易用,无需额外依赖
- 开源稳定,维护活跃,适合简单到中等复杂度的文档转换
方案3:静默使用Microsoft Print to PDF(无额外库)
如果你不想引入第三方库,可以通过配置打印队列实现静默打印,同时监听打印状态解决无通知问题:
示例代码
using System; using System.Threading.Tasks; using System.Printing; using System.Windows.Documents; public async Task GeneratePdfSilently(FlowDocument flowDoc, string outputPdfPath) { // 获取系统内置的Microsoft Print to PDF队列 var printQueue = new PrintQueue(new PrintServer(), "Microsoft Print to PDF"); // 配置打印参数,指定输出文件路径,跳过弹窗 var printTicket = printQueue.DefaultPrintTicket; printTicket.OutputFileName = outputPdfPath; printTicket.PrintToFile = true; // 提交打印作业 var paginator = ((IDocumentPaginatorSource)flowDoc).DocumentPaginator; var printJob = printQueue.AddJob("FlowDocument PDF Export", paginator, true); // 监听打印完成状态 await Task.Run(() => { while (!printJob.IsCompleted && !printJob.IsFailed && !printJob.IsCanceled) { System.Threading.Thread.Sleep(100); } if (printJob.IsFailed) { throw new InvalidOperationException("PDF生成失败:" + printJob.JobStatus); } // 打印完成后可在此添加通知逻辑 }); }
说明
- 无需额外依赖,利用系统原生驱动
- 依赖Windows系统环境,需确保Microsoft Print to PDF驱动已安装
- 通过轮询打印作业状态解决无完成通知的问题
内容的提问来源于stack exchange,提问作者Dan Stevens
相关产品推荐
相关产品推荐

