using System; using System.Collections.Generic; using System.Data; using System.Linq; using System.Windows.Forms; using System.Text; using System.Threading.Tasks; using System.Net; using Report.Entity; using FastReport.Utils; using System.IO; using System.Reflection; using FastReport.Cloud.OAuth; using Spire.Pdf; using System.Printing; using Spire.Pdf.Exporting.XPS.Schema; using System.Threading; using System.Drawing.Printing; namespace ReportLibrary { public class ReportHelper { private static readonly LocalPrintServer _printServer = new LocalPrintServer(); public ReportHelper() { } public static List ToPicTable(Dictionary dict, string websiteUrl) { List picList = new List(); piclog pic = new piclog(); string key = "hisLog"; if (dict.ContainsKey(key) == true) { var baseUri = new Uri(websiteUrl); var fullUri = new Uri(baseUri, dict[key]); pic.photo = fullUri.AbsoluteUri; } key = "firstPage"; if (dict.ContainsKey(key) == true) { var baseUri = new Uri(websiteUrl); var fullUri = new Uri(baseUri, dict[key]); pic.firstPage = fullUri.AbsoluteUri; } key = "pageHeader"; if (dict.ContainsKey(key) == true) { var baseUri = new Uri(websiteUrl); var fullUri = new Uri(baseUri, dict[key]); pic.pageHeader = fullUri.AbsoluteUri; } key = "pageFooter"; if (dict.ContainsKey(key) == true) { var baseUri = new Uri(websiteUrl); var fullUri = new Uri(baseUri, dict[key]); pic.pageFooter = fullUri.AbsoluteUri; } key = "resultSign"; if (dict.ContainsKey(key) == true) { var baseUri = new Uri(websiteUrl); var fullUri = new Uri(baseUri, dict[key]); pic.resultSign = fullUri.AbsoluteUri; } key = "orgSign"; if (dict.ContainsKey(key) == true) { var baseUri = new Uri(websiteUrl); var fullUri = new Uri(baseUri, dict[key]); pic.orgSign = fullUri.AbsoluteUri; } key = "picExtOne"; if (dict.ContainsKey(key) == true) { var baseUri = new Uri(websiteUrl); var fullUri = new Uri(baseUri, dict[key]); pic.picExtOne = fullUri.AbsoluteUri; } key = "picExtTwo"; if (dict.ContainsKey(key) == true) { var baseUri = new Uri(websiteUrl); var fullUri = new Uri(baseUri, dict[key]); pic.picExtTwo = fullUri.AbsoluteUri; } key = "picExtThree"; if (dict.ContainsKey(key) == true) { var baseUri = new Uri(websiteUrl); var fullUri = new Uri(baseUri, dict[key]); pic.picExtThree = fullUri.AbsoluteUri; } key = "picExtFour"; if (dict.ContainsKey(key) == true) { var baseUri = new Uri(websiteUrl); var fullUri = new Uri(baseUri, dict[key]); pic.picExtFour = fullUri.AbsoluteUri; } key = "picExtFive"; if (dict.ContainsKey(key) == true) { var baseUri = new Uri(websiteUrl); var fullUri = new Uri(baseUri, dict[key]); pic.picExtFive = fullUri.AbsoluteUri; } key = "picExtSix"; if (dict.ContainsKey(key) == true) { var baseUri = new Uri(websiteUrl); var fullUri = new Uri(baseUri, dict[key]); pic.picExtSix = fullUri.AbsoluteUri; } key = "picExtSeven"; if (dict.ContainsKey(key) == true) { var baseUri = new Uri(websiteUrl); var fullUri = new Uri(baseUri, dict[key]); pic.picExtSeven = fullUri.AbsoluteUri; } key = "picExtEight"; if (dict.ContainsKey(key) == true) { var baseUri = new Uri(websiteUrl); var fullUri = new Uri(baseUri, dict[key]); pic.picExtEight = fullUri.AbsoluteUri; } key = "picExtNine"; if (dict.ContainsKey(key) == true) { var baseUri = new Uri(websiteUrl); var fullUri = new Uri(baseUri, dict[key]); pic.picExtNine = fullUri.AbsoluteUri; } key = "picExtTen"; if (dict.ContainsKey(key) == true) { var baseUri = new Uri(websiteUrl); var fullUri = new Uri(baseUri, dict[key]); pic.picExtTen = fullUri.AbsoluteUri; } picList.Add(pic); return picList; } public async Task ReportExport(RequestExport req, DataSet ds) { Task task = Task.Factory.StartNew(() => { using (FastReport.Report report = new FastReport.Report()) { report.Load(req.TemplatePath); foreach (var item in req.Parameters) { report.SetParameterValue(item.Name, item.Value); } report.RegisterData(ds); report.PrintSettings.ShowDialog = false; FastReport.EnvironmentSettings eSet = new FastReport.EnvironmentSettings(); eSet.ReportSettings.ShowProgress = false; report.Prepare(); if (req.FileFormat.Equals("WORD")) { //FastReport.Export.RichText.RTFExport export = new FastReport.Export.RichText.RTFExport(); //export.ShowProgress = true; //report.Export(export, req.FilePath); string path_current = System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); string file_path = string.Format("{0}\\{1}", path_current, "temp.pdf"); FastReport.Export.Pdf.PDFExport pdfExport = new FastReport.Export.Pdf.PDFExport(); report.Export(pdfExport, file_path); PdfDocument pdf = new PdfDocument(); //加载PDF文档 pdf.LoadFromFile(file_path); //将PDF文档转为Word文档并保存,可选择格式 pdf.SaveToFile(req.FilePath, FileFormat.DOCX); } else if (req.FileFormat.Equals("EXCEL")) { //FastReport.Export.OoXML.Excel2007Export xlsExport = new FastReport.Export.OoXML.Excel2007Export(); //report.Export(xlsExport, req.FilePath); string path_current = System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); string file_path = string.Format("{0}\\{1}", path_current, "temp.pdf"); FastReport.Export.Pdf.PDFExport pdfExport = new FastReport.Export.Pdf.PDFExport(); report.Export(pdfExport, file_path); PdfDocument pdf = new PdfDocument(); //加载PDF文档 pdf.LoadFromFile(file_path); //将PDF文档转为Word文档并保存,可选择格式 pdf.SaveToFile(req.FilePath, FileFormat.XLSX); } else { if (File.Exists(req.FilePath)) { File.Delete(req.FilePath); } if (!string.IsNullOrEmpty(req.customerOrgName)) { string dirPath = System.IO.Path.GetDirectoryName(req.FilePath); string fileName=System.IO.Path.GetFileName(req.FilePath); string tempPath = System.IO.Path.Combine(dirPath, req.customerOrgName); if (!Directory.Exists(tempPath)) { Directory.CreateDirectory(tempPath); } if (!string.IsNullOrEmpty(req.departmentName)) { tempPath = System.IO.Path.Combine(tempPath,req.departmentName); if (!Directory.Exists(tempPath)) { Directory.CreateDirectory(tempPath); } } req.FilePath=System.IO.Path.Combine(tempPath, fileName); //MessageBox.Show(req.FilePath); } FastReport.Export.Pdf.PDFExport pdfExport = new FastReport.Export.Pdf.PDFExport(); report.Export(pdfExport, req.FilePath); } } return "Success"; }); String taskResult = await task; return taskResult; } public string GetDefaultPrinter() { using (PrintDocument pd = new PrintDocument()) { return pd.PrinterSettings.PrinterName; } } /* try { using (var cts = new CancellationTokenSource()) { // 关键点1:设置5分钟超时 cts.CancelAfter(TimeSpan.FromMinutes(5)); var result = await Task.Run(async () => { using (var report = new FastReport.Report()) { // 加载报表模板 report.Load(req.TemplatePath); report.RegisterData(ds); // 设置参数 foreach (var param in req.Parameters) { report.SetParameterValue(param.Name, param.Value); } // 配置打印机 if (!string.IsNullOrEmpty(req.Printer)) { report.PrintSettings.Printer = req.Printer.Trim(); } // 执行打印 report.PrintSettings.ShowDialog = req.IsPrintOption == "Y"; report.Print(); // 监控打印状态 string jobName = System.IO.Path.GetFileName(req.TemplatePath); return await new PrintMonitor().CheckPrintStatusAsync( GetDefaultPrinter(), jobName, cts.Token, TimeSpan.FromMinutes(3)); } }, cts.Token); return result; } } catch (OperationCanceledException ex) { // 关键点2:区分超时和手动取消 return ex.CancellationToken.IsCancellationRequested ? "用户手动取消打印" : "打印超时(5分钟未完成)"; } catch (Exception ex) when (ex.Message.Contains("缺纸")) { return "打印机缺纸,请装纸后重试"; } catch (Exception ex) { return $"打印失败: {ex.Message}"; }*/ // 创建超时控制源(外层) public async Task ReportPrint(RequestPrint req, DataSet ds) { var combinedCts = new CancellationTokenSource(); combinedCts.CancelAfter(TimeSpan.FromSeconds(30)); try { return await Task.Run(async () => { var report = new FastReport.Report(); var monitor = new PrintMonitor(); var printCts = CancellationTokenSource.CreateLinkedTokenSource(combinedCts.Token); var printerName = GetPrinterName(req); printCts.CancelAfter(TimeSpan.FromSeconds(30)); try { // 加载报表模板 if (!File.Exists(req.TemplatePath)) throw new FileNotFoundException("报表模板文件不存在", req.TemplatePath); report.Load(req.TemplatePath); report.RegisterData(ds); // 配置打印机参数 if (!IsPrinterAvailable(printerName)) throw new InvalidOperationException($"打印机不可用: {printerName}"); ConfigurePrinter(report, req); // 虚拟打印机特殊处理 if (IsVirtualPrinter(printerName)) { report.PrintSettings.ShowDialog = false; // 禁用对话框 // report.PrintSettings.ShowProgress = false; } report.Print(); var jobName = GenerateJobName(req); return await monitor.CheckPrintStatusAsync( printerName, jobName, printCts.Token); } catch (Exception ex) { // 添加虚拟打印机调试信息 if (IsVirtualPrinter(printerName)) throw new Exception($"虚拟打印机处理失败: {ex.Message} [文件:{req.TemplatePath}]", ex); throw new Exception($"打印操作失败: {ex.Message}", ex); } }, combinedCts.Token); } catch (OperationCanceledException ex) when (combinedCts.IsCancellationRequested) { throw new TimeoutException("操作超时,请检查打印机响应", ex); } catch (Exception ex) { // 解析异常链 var errorMsg = new StringBuilder("打印流程异常:"); var innerEx = ex; while (innerEx != null) { errorMsg.AppendLine().Append($"→ {innerEx.GetType().Name}: {innerEx.Message}"); innerEx = innerEx.InnerException; } // 记录完整堆栈 //Logger.Error(ex, errorMsg.ToString()); // 返回友好提示 if (ex is FileNotFoundException) return "ERROR: 模板文件路径错误"; if (ex.Message.Contains("虚拟打印机")) return "ERROR: 虚拟打印机处理失败,请检查输出文件路径"; return $"ERROR: 打印系统异常({ex.GetBaseException().Message})"; } } // 打印机检测方法 private bool IsPrinterAvailable(string printerName) { return PrinterSettings.InstalledPrinters .Cast() .Any(p => p.Equals(printerName, StringComparison.OrdinalIgnoreCase)); } // 虚拟打印机检测(根据名称特征判断) private bool IsVirtualPrinter(string printerName) { var virtualPrinters = new[] { "Microsoft Print to PDF", "OneNote", "Fax" }; return virtualPrinters.Any(v => printerName.Contains(v)); } private void ConfigurePrinter(FastReport.Report report, RequestPrint req) { if (!string.IsNullOrEmpty(req.Printer)) { report.PrintSettings.Printer = req.Printer.Trim(); } } private string GenerateJobName(RequestPrint req) { return System.IO.Path.GetFileNameWithoutExtension(req.TemplatePath); } private string GetPrinterName(RequestPrint req) { return string.IsNullOrEmpty(req.Printer) ? GetDefaultPrinter() : req.Printer; } public async Task ReportPrintPre(RequestPrintPre req, DataSet ds) { MemoryStream strm = new MemoryStream(); Task task = Task.Factory.StartNew(() => { using (FastReport.Report report = new FastReport.Report()) { report.Load(req.TemplatePath); foreach (var item in req.Parameters) { report.SetParameterValue(item.Name, item.Value); } report.RegisterData(ds); report.PrintSettings.ShowDialog = false; FastReport.EnvironmentSettings eSet = new FastReport.EnvironmentSettings(); eSet.ReportSettings.ShowProgress = false; report.Prepare(); FastReport.Export.Pdf.PDFExport pdfExport = new FastReport.Export.Pdf.PDFExport(); report.Report.Export(pdfExport, strm); } if (req.IsUploadPdf.Equals("Y")) return CreatePdfFile(strm, req.IsDev, true); else return CreatePdfFile(strm, req.IsDev, false); }); String taskResult = await task; return taskResult; } public static void ReportDesign(RequestDesign req) { using (FastReport.Report report = new FastReport.Report()) { FastReport.EnvironmentSettings eSet = new FastReport.EnvironmentSettings(); eSet.ReportSettings.ShowProgress = false; string filePath = req.TemplatePath.Replace("//", "\\"); report.Load(filePath); foreach (var item in req.Parameters) { report.SetParameterValue(item.Name, item.Value); } //DataSet ds = ClientConfig.DeserializeObject(req.DataSetJson); DataSet ds = ClientConfig.ConvertJsonToDataSet(req.DataSetJson, req.ImageUrl,req.ApiUrl); report.RegisterData(ds); //report.Prepare report.Design(); report.Save(filePath); //TemplateDesignForm frm = new TemplateDesignForm(report, filePath); //frm.ShowDialog(); } } private string CreatePdfFile(MemoryStream strm, bool IsDev,bool isUploadPdf) { string path_current = System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); DirectoryInfo path_current_info = new DirectoryInfo(path_current); string path_parent = string.Empty; string dirPath= string.Empty; string filePath = string.Empty; //string file_path = "\\static\\fastReport\\output\\pdf\\print.pdf"; if (!isUploadPdf) { string path_parent_path = path_current_info.Parent.FullName; if (IsDev) { path_parent_path = path_parent_path.Replace("extensions", "public"); } else { path_parent_path = path_parent_path.Replace("extensions", "dist"); } path_parent = path_parent_path + "\\static\\fastReport\\output\\pdf"; if (!Directory.Exists(path_parent)) { Directory.CreateDirectory(path_parent); } dirPath = path_parent; filePath = path_parent + string.Format("\\{0}.pdf",DateTime.Now.ToString("yyyyMMddHHmmss")); }else { filePath = path_current_info.FullName + "\\upload.pdf"; } if (!string.IsNullOrEmpty(dirPath)) { foreach (string file in Directory.GetFiles(dirPath)) { string fileName = System.IO.Path.GetFileName(file); if (fileName.Equals("print.pdf")) continue; File.Delete(file); } } if (File.Exists(filePath)) { File.Delete(filePath); } //MessageBox.Show("CreatePdfFile"); FileStream fs = new FileStream(filePath, FileMode.OpenOrCreate); BinaryWriter w = new BinaryWriter(fs); w.Write(strm.ToArray()); fs.Close(); strm.Close(); return System.IO.Path.GetFileName(filePath); } } }