using Microsoft.Web.WebView2.Core; using Microsoft.Web.WebView2.WinForms; using Newtonsoft.Json.Linq; using PdfiumViewer; using prBrowser; using System; using System.Collections.Generic; using System.Drawing.Printing; using System.IO; using System.Linq; using System.Net.Http; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; namespace PrintHtml { public class PrintHtml { private readonly HttpClient _httpClient = new HttpClient(); // 重用 HttpClient 实例 Thread thread; string inputParams = ""; dynamic paperobj; PrintSettings settings; [STAThread] public string PrintUrlHtml(string input) { System.Diagnostics.Debugger.Launch(); String errorCode = "0"; String errorMessage = ""; inputParams = input; JObject output = new JObject(); JArray fileStringArray = new JArray(); try { dynamic inputobj = Newtonsoft.Json.JsonConvert.DeserializeObject(input); var paramsobj = inputobj["params"][0]; thread = new Thread(new ThreadStart(ReportFormd)); thread.SetApartmentState(ApartmentState.STA); //重点 thread.Start(); thread.Join(); } catch (Exception ex) { errorMessage = ex.Message; } output.Add("errorCode", errorCode); output.Add("errorMessage", errorMessage); return output.ToString(); } private void ReportFormd() { try { PrinFrom dForm = new PrinFrom(inputParams); dForm.ShowDialog(); } catch (Exception ex2) { } thread.Abort(); } public string PrintInfo(string inputString) { string output = ""; output = Task.Run(async () => await PrintURLAsync(inputString)).Result; return output; } /// /// 打印指定 URL 的 PDF 文件。 /// /// 输入参数的 JSON 字符串 /// 操作结果的 JSON 字符串 public async Task PrintURLAsync(string inParams) { //System.Diagnostics.Debugger.Launch(); string errorCode = "0"; string errorMessage = "打印成功"; string tempPdfPath = string.Empty; PdfDocument pdfDocument = null; PrintDocument pdfPrintDoc = null; try { if (string.IsNullOrWhiteSpace(inParams)) { return CreateErrorResponse("-1", "输入参数不能为空"); } var inParamsObj = JObject.Parse(inParams); var inParamsResult = inParamsObj["result"]; string url = inParamsResult?["url"]?.ToString(); if (string.IsNullOrWhiteSpace(url)) { return CreateErrorResponse("-1", "URL 不能为空"); } // 确保临时目录存在 // 确保临时目录存在 string tempDir = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location); tempDir = tempDir + "\\tmpPDF"; tempPdfPath = Path.Combine(tempDir, $"{Guid.NewGuid()}.pdf"); // 1. 异步下载 PDF 文件 bool downloaded = await DownloadPdfFileAsync(url, tempPdfPath); if (!downloaded) { return CreateErrorResponse("-1", "PDF 文件下载失败"); } paperobj = inParamsObj["printParameters"]; if (paperobj == null) { paperobj = new JObject { ["PaperName"] = "A4", ["Landscape"] = false, ["ManualDuplex"]= false }; } // 2. 配置打印机设置 GetPrintSettings(); // 3. 加载 PDF 并打印 PrintPdf pdf = new PrintPdf(); pdf.Print(tempPdfPath, settings); // 成功打印后返回成功信息 return CreateResponseString(errorCode, errorMessage, new JObject()); } catch (Exception ex) { //Console.WriteLine($"PrintURLAsync 发生未处理异常: {ex}"); errorCode = "-1"; errorMessage = $"打印 PDF 时发生错误: {ex.Message}"; // 异常时也返回字符串 return CreateResponseString(errorCode, errorMessage, new JObject()); } finally { // 5. 释放资源并清理临时文件 if (!string.IsNullOrEmpty(tempPdfPath) && File.Exists(tempPdfPath)) { try { File.Delete(tempPdfPath); } catch (Exception ex) { // 记录删除失败日志,但不应中断主流程 //Console.WriteLine($"警告:无法删除临时文件 {tempPdfPath}: {ex.Message}"); } } } // 这行代码理论上不会执行到,因为 try/catch 块都会 return } /// /// 异步下载 PDF 文件。(兼容 .NET Framework) /// /// PDF 文件的 URL /// 保存到本地的文件路径 /// 下载是否成功 private async Task DownloadPdfFileAsync(string url, string filePath) { try { // 发送 GET 请求获取内容流 using (HttpResponseMessage response = await _httpClient.GetAsync(url, HttpCompletionOption.ResponseHeadersRead)) { if (response.IsSuccessStatusCode) { // 使用 FileStream 异步写入 using (FileStream fileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None, bufferSize: 8192, useAsync: true)) { // 获取响应内容流 using (Stream contentStream = await response.Content.ReadAsStreamAsync()) { // 异步复制内容流到文件流 await contentStream.CopyToAsync(fileStream); } } return true; } else { //Console.WriteLine($"无法下载文件,状态码:{response.StatusCode}"); return false; } } } catch (Exception ex) { //Console.WriteLine($"下载过程中发生错误:{ex.Message}"); return false; } } /// /// 根据参数配置打印机设置。 /// /// 打印机参数的 JSON 字符串 /// 配置好的 PrinterSettings 对象 private void GetPrinterSettings(PrintSettings settings) { PrinterSettings printerSettings = new PrinterSettings(); if (paperobj != null) { if (paperobj["PrinterName"] != null && !string.IsNullOrEmpty(paperobj["PrinterName"].ToString())) { foreach (PrinterSettings printer in PrinterSettings.InstalledPrinters) { if (printer.PrinterName == paperobj["PrinterName"].ToString()) { printerSettings = printer; break; } } } } PaperSize paperSize = new PaperSize(); string paperName = "A4"; if (paperobj["PaperName"] != null && !"A4".Equals(paperobj["PaperName"].ToString())) { paperName = paperobj["PaperName"].ToString(); } foreach (PaperSize size in printerSettings.PaperSizes) { if (size.PaperName == paperName) { paperSize = size; break; } } settings.SelectedPaperSize = paperSize; printerSettings.DefaultPageSettings.PaperSize = paperSize; printerSettings.DefaultPageSettings.Margins.Left = 0; printerSettings.DefaultPageSettings.Margins.Right = 0; printerSettings.DefaultPageSettings.Margins.Bottom = 0; printerSettings.DefaultPageSettings.Landscape = settings.IsLandscape; printerSettings.Copies = (short)settings.Copies; if (settings.PrintedByRange) { printerSettings.PrintRange = PrintRange.SomePages; printerSettings.FromPage = settings.FromPage; printerSettings.ToPage = settings.ToPage; } printerSettings.Duplex = settings.Duplex; settings.printerSettings = printerSettings; } public PrintSettings GetPrintSettings() { settings = new PrintSettings(); if (paperobj != null) { if (paperobj["Landscape"] != null && !string.IsNullOrEmpty(paperobj["Landscape"].ToString())) { settings.IsLandscape = bool.Parse(paperobj["Landscape"].ToString()); } if (paperobj["Copies"] != null && !string.IsNullOrEmpty(paperobj["Copies"].ToString())) { settings.Copies = int.Parse(paperobj["Copies"].ToString()); // 打印份数,默认是1 } if (paperobj["ManualDuplex"] != null && !string.IsNullOrEmpty(paperobj["ManualDuplex"].ToString())) { settings.manualDuplex = bool.Parse(paperobj["ManualDuplex"].ToString()); } settings.Duplex = Duplex.Simplex; if (paperobj["Duplex"] != null) { if (paperobj["Duplex"].ToString() == "Horizontal") { settings.Duplex = Duplex.Horizontal; } if (paperobj["Duplex"].ToString() == "Vertical") { settings.Duplex = Duplex.Vertical; } } if (paperobj["PageRanges"] != null) { string pageRanges = paperobj["PageRanges"].ToString(); if (!string.IsNullOrEmpty(pageRanges)) { settings.PrintedByRange = true; if (pageRanges.IndexOf("-") > 0) { settings.FromPage = int.Parse(pageRanges.Split("-".ToCharArray())[0]); settings.ToPage = int.Parse(pageRanges.Split("-".ToCharArray())[0]); } else { settings.FromPage = int.Parse(pageRanges); settings.ToPage = settings.FromPage; } } } if (paperobj["DuplexTip"] != null) { string _duplexTips = paperobj["DuplexTip"].ToString(); if (!string.IsNullOrEmpty(_duplexTips)) { settings.duplexTips = _duplexTips; } } } GetPrinterSettings(settings); return settings; } private async Task PrintPdfWithWebView2(string pdfPath) { // 创建一个不可见的 WinForms 窗口来承载 WebView2 using (var form = new Form()) { // 设置窗口为不可见,不显示在任务栏 form.WindowState = FormWindowState.Minimized; form.ShowInTaskbar = false; form.Opacity = 0; // 完全透明 form.Visible = false; // 完全隐藏 var webView2 = new WebView2 { Dock = DockStyle.Fill }; form.Controls.Add(webView2); // 初始化 WebView2 await webView2.EnsureCoreWebView2Async(null); // 设置 PDF 文件的 URL string fileUrl = new Uri(pdfPath).AbsoluteUri; webView2.CoreWebView2.Navigate(fileUrl); // 等待页面加载完成 TaskCompletionSource printTask = new TaskCompletionSource(); webView2.CoreWebView2.NavigationCompleted += async (sender, e) => { if (e.IsSuccess) { // 等待一段时间确保 PDF 完全加载 await Task.Delay(2000); // 增加等待时间以确保 PDF 完全渲染 try { // 调用 JavaScript 的 window.print() 方法 await webView2.CoreWebView2.ExecuteScriptAsync("window.print();"); } catch (Exception ex) { // 如果打印失败,记录错误但继续 Console.WriteLine($"打印调用失败: {ex.Message}"); } // 设置任务完成 printTask.SetResult(true); } else { printTask.SetException(new Exception($"PDF 加载失败: {e.WebErrorStatus}")); } }; // 启动消息循环 form.Show(); // 等待打印完成或超时 var timeoutTask = Task.Delay(TimeSpan.FromSeconds(30)); // 30秒超时 var completedTask = await Task.WhenAny(printTask.Task, timeoutTask); if (completedTask == timeoutTask) { throw new TimeoutException("PDF 打印超时"); } // 确保表单关闭 form.Invoke((MethodInvoker)delegate { form.Close(); }); } } private string CreateErrorResponse(string errorCode, string errorMessage) { return CreateResponseString(errorCode, errorMessage, new JObject()); // 确保返回 string } private string CreateResponseString(string errorCode, string errorMessage, JObject result) { return CreateResponse(errorCode, errorMessage, result).ToString(); // 调用 JObject 版本并转为 string } private JObject CreateResponse(string errorCode, string errorMessage, JObject result) { var output = new JObject { ["errorCode"] = errorCode, ["errorMessage"] = errorMessage, ["result"] = result ?? new JObject() }; return output; // 返回 JObject } } }