背景 最近有一个需求涉及到静默打印
,也就是打印时不需要弹出打印配置框,而是直接调用打印机
在实际生产中,采用的是FastReport实现静默打印方案,以下仅供参考
方案 经过讨论大概是以下几种方案:
把打印配置弹窗干掉、模拟点击打印事件
浏览器实现静默打印
本地运行一个服务,客户端返回请求状态后请求本地接口调用打印
方案1 第一种没有去尝试,所以先讲讲第二种解决方案,通过前端控制浏览器打印,但是百度一圈下来的解决方案都是通过设置浏览器参数,然后创建一个快捷程序并设置启动参数,操作很简单,但实在不符合需求,总不能给每个客户也这样配置一边吧,所以第二种也pass
。
操作如下:
方案3 重点讲一下方案,也是目前在探索中,后续有更好的方法会发出来,也欢迎各位提出更好的解决方案。
目前仅支持windows环境,winform
最终是.exe
程序
使用VS2019
创建
拖入ComboBox
控件,用来选择本地打印机
获取打印机列表填充下拉 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 private void InitPrinterList ( ){ var print = new PrintDocument(); var defaultPrinter = print.PrinterSettings.PrinterName; for (var i = 0 ; i < PrinterSettings.InstalledPrinters.Count; i++) { var tmp = PrinterSettings.InstalledPrinters[i]; if (tmp == defaultPrinter) { tmp += "(默认)" ; } this .comboBox1.Items.Add(tmp); } } private void Form1_Load (object sender, EventArgs e ){ InitPrinterList(); }
ctrl+f5
运行窗体查看效果
创建服务 没有使用socket
,而是在winform
中创建了一个http
服务,并开放端口供浏览器本地请求
先新增两个依赖:
BeetleX 1.5.1.7
BeetleX.FastHttpApi 1.8.2.61
这两个版本是支持.net framework
的,BeetleX 是一个基于.Net Core开发的一个开源跨平台TCP通讯框架,它提供了完整的会话服务管理,协议分析扩展,TLS支持和缓冲区管理等完全服务基础功能。有兴趣的可以去Github参观一下。
初始化Http服务 在Load方法中调用InitHttpServer()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 protected void InitHttpServer ( ){ _httpApiServer = new HttpApiServer(new HttpOptions() { Port = 9000 , LogToConsole = true , LogLevel = BeetleX.EventArgs.LogType.Debug }); _httpApiServer.IPv4Tables.AddWhite("127.0.0.1/24" ); _httpApiServer.Options.CrossDomain = new OptionsAttribute() { AllowOrigin = "*" , AllowMethods = "*" , AllowHeaders = "*" }; _httpApiServer.Register(typeof (Home).Assembly); _httpApiServer.Open(); }
注册的程序就是Controller
1 2 3 4 5 6 7 8 9 10 11 12 13 [Controller(BaseUrl = "/home" ) ] public class Home { public object Hello (string name ) { return new { Hello = "hello " + name, Time = DateTime.Now }; } }
控制下服务的生命周期
使用Postman
请求一下
http://localhost:9000/home/Hello?name=test
返回成功
打印 客户端向本地请求打印接口,传入参数
这里传入了pdf文件地址,通过请求文件并打印
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 public void Print (string url, int printCount ){ url = url.Replace("\n " , "" ); if (!(WebRequest.Create(url) is HttpWebRequest request)) return ; if (!(request.GetResponse() is HttpWebResponse response)) return ; var stream = response.GetResponseStream(); var pdf = new InputPdf(ReadFully(stream)); var printJob = new PrintJob(Printer.Default, pdf); printJob.PrintOptions.Copies = printCount; printJob.Print(); } public static byte [] ReadFully (Stream input ){ using (var ms = new MemoryStream()) { input.CopyTo(ms); return ms.ToArray(); } }
打印插件调用的DynamicPdf
打印插件文档:https://www.dynamicpdf.com/docs/dotnet/print-manager-print-options
优化建议: 可以通过下拉框选择的打印机打印,需要记录选择的打印机
通过读取和设置config
值实现,引入System.Configuration
ConfigHelper类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 public static class ConfigHelper { public static string GetAppConfig (string strKey ) { var file = System.Windows.Forms.Application.ExecutablePath; var config = ConfigurationManager.OpenExeConfiguration(file); return config.AppSettings.Settings.AllKeys.Any(key => key == strKey) ? config.AppSettings.Settings[strKey].Value.ToString() : null ; } public static void UpdateAppConfig (string newKey, string newValue ) { var file = System.Windows.Forms.Application.ExecutablePath; var config = ConfigurationManager.OpenExeConfiguration(file); var exist = false ; foreach (var key in config.AppSettings.Settings.AllKeys) { if (key == newKey) { exist = true ; } } if (exist) { config.AppSettings.Settings.Remove(newKey); } config.AppSettings.Settings.Add(newKey, newValue); config.Save(ConfigurationSaveMode.Modified); ConfigurationManager.RefreshSection("appSettings" ); } }
设置下拉选择事件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 private void comboBox1_SelectedIndexChanged (object sender, EventArgs e ){ var selectedPrint = this .comboBox1.SelectedItem.ToString(); if (string .IsNullOrEmpty(selectedPrint)) { return ; } if (selectedPrint.Contains("默认" )) { selectedPrint = selectedPrint.Replace("(默认)" , "" ); } ConfigHelper.UpdateAppConfig("defaultPrint" , selectedPrint); }
优化后的打印接口 1 2 3 4 5 6 7 8 ... var defaultPrinter = ConfigHelper.GetAppConfig("defaultPrint" );var printer = new Printer(defaultPrinter);var pdf = new InputPdf(ReadFully(stream));var printJob = new PrintJob(printer, pdf);...
这样就能实现简单的静默打印,当然还有很多欠缺之处,后续优化,不当之处请指出