| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428 |
- 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<dynamic>(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;
- }
- /// <summary>
- /// 打印指定 URL 的 PDF 文件。
- /// </summary>
- /// <param name="inParams">输入参数的 JSON 字符串</param>
- /// <returns>操作结果的 JSON 字符串</returns>
- public async Task<string> 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
- }
- /// <summary>
- /// 异步下载 PDF 文件。(兼容 .NET Framework)
- /// </summary>
- /// <param name="url">PDF 文件的 URL</param>
- /// <param name="filePath">保存到本地的文件路径</param>
- /// <returns>下载是否成功</returns>
- private async Task<bool> 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;
- }
- }
- /// <summary>
- /// 根据参数配置打印机设置。
- /// </summary>
- /// <param name="printParametersJson">打印机参数的 JSON 字符串</param>
- /// <returns>配置好的 PrinterSettings 对象</returns>
-
- 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<bool> printTask = new TaskCompletionSource<bool>();
- 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
- }
- }
- }
|