使用XpsToPDF C#转换XPS到PDF时遇StaticResource找不到错误
XPS转PDF时出现StaticResource未找到错误的解决及替代方案
错误原因分析
- 该错误源于PdfSharp的XPS解析器无法定位XPS文件中引用的静态资源(如路径几何、自定义画笔等)。这类资源通常在XPS包的
Resources节点定义,报错的XPS文件可能存在资源引用路径错误、资源未正确嵌入,或者其复杂的资源结构超出了PdfSharp的兼容范围。 - 从堆栈跟踪来看,错误触发于解析
PathGeometry的环节,说明问题集中在XPS文件的路径资源引用逻辑上。
针对PdfSharp的修复尝试
1. 修正临时文件处理逻辑
当前代码中提前创建空PDF再覆盖的操作完全多余,且可能引发异常。修正后的代码如下:
stream.Seek(0, SeekOrigin.Begin); // 生成唯一命名的临时XPS文件,避免并发冲突 string tempXpsFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, $"XPSTemp_{Guid.NewGuid()}.xps"); using (var fs = new FileStream(tempXpsFilePath, FileMode.Create, FileAccess.Write)) { stream.CopyTo(fs); } string tempPdfFilePath = Path.GetTempFileName(); // 直接执行XPS转PDF,无需提前创建空PDF XpsConverter.Convert(tempXpsFilePath, tempPdfFilePath, 0); MemoryStream pdfStream = new MemoryStream(); using (var fs = new FileStream(tempPdfFilePath, FileMode.Open, FileAccess.Read)) { fs.CopyTo(pdfStream); } pdfStream.Position = 0; // 转换完成后清理临时文件 File.Delete(tempXpsFilePath); File.Delete(tempPdfFilePath); Response.Headers.Add("Content-Type", "application/pdf"); var encodedFileName = System.Web.HttpUtility.UrlEncode(fileData.name); Response.Headers.Add("Content-Disposition", $"attachment; filename=\"{Path.ChangeExtension(encodedFileName, ".pdf")}\""); return new FileStreamResult(pdfStream, "application/pdf");
2. 验证XPS文件完整性
将报错的XPS文件解压(XPS本质是ZIP格式),检查FixedDocument.fdoc或对应页面文件中的StaticResource R0引用,确认目标资源是否存在于Resources目录下。若资源缺失或路径错误,手动修正后再尝试转换。
3. 升级PdfSharp版本
若使用的是旧版PdfSharp,升级至最新稳定版,新版本可能修复了部分XPS解析的兼容性问题。
免费替代方案
如果PdfSharp的兼容性问题无法解决,可尝试以下方案:
1. Ghostscript命令行转换
Ghostscript对XPS的支持更为完善,需先安装Ghostscript,再通过代码调用命令行:
stream.Seek(0, SeekOrigin.Begin); string tempXpsFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, $"XPSTemp_{Guid.NewGuid()}.xps"); using (var fs = new FileStream(tempXpsFilePath, FileMode.Create, FileAccess.Write)) { stream.CopyTo(fs); } string tempPdfFilePath = Path.GetTempFileName(); // 调用Ghostscript命令(根据系统选择32/64位版本,如gswin32c.exe) var processStartInfo = new ProcessStartInfo { FileName = "gswin64c.exe", Arguments = $"-dNOPAUSE -dBATCH -sDEVICE=pdfwrite -sOutputFile=\"{tempPdfFilePath}\" \"{tempXpsFilePath}\"", RedirectStandardOutput = true, RedirectStandardError = true, UseShellExecute = false, CreateNoWindow = true }; using (var process = Process.Start(processStartInfo)) { process.WaitForExit(); // 可读取错误日志排查问题 string errorLog = process.StandardError.ReadToEnd(); if (!string.IsNullOrEmpty(errorLog)) { // 处理转换错误 } } // 后续PDF流处理、临时文件清理同之前逻辑
2. 基于Windows原生XPS服务转换
利用Windows系统自带的XPS打印功能,通过PrintDocument类实现转换,但该方案依赖系统环境,仅适用于Windows平台。
内容的提问来源于stack exchange,提问作者Лев Герасимов
相关产品推荐
相关产品推荐

