
简介Lodop 6.057 打印控件资源包适用于需要在 Chrome、IE、Firefox 等浏览器中实现本地打印的 Web 开发者。该版本发布于 2012 年虽时间较早但稳定易用作者称终身免费入手简单、功能强悍可满足票据、报表、标签等常见打印场景。压缩包共 50 个文件以 47 个 HTML 示例页面为主配合 LodopFuncs.js 封装脚本、CSS 样式和 install_lodop.exe 安装程序基本覆盖安装、调用、预览、分页、样式调整等常用功能整体仅 1.72MB。已有 1191 人学习下载。包内提供多组完整示例既能看到前端如何引入控件、生成打印任务也能了解不同纸张与排版参数的设置方法开发者对照修改即可集成到自己的项目省去大量摸索时间尤其适合刚接触打印控件的初中级工程师。1. 为什么还用 lodop 6.057网页打印的硬骨头还是要控件啃把 lodop 6.0572012 最新版打印控件从下载包里捡回来用是我接手一个仓储打印模块时的事拣货单、出库单、盘点标签都要通过浏览器打可一到套打就翻车——底图对不上、多联单错位、批量打印只能一遍遍点预览。这个控件解决的是浏览器原生打印不擅长的场景精确坐标排版、静默输出、条码和表格套打。它靠本地插件方式让网页直接驱动打印机当年在 chrome、IE、firefox 三个浏览器上都走通了而且不按年收费。适合谁被票据、单据、标签打印折磨的前后端开发者以及要维护老打印系统又不打算重构的运维。下载包里带了安装程序、示例页和内置文档照着下面流程就能把环境跑起来。2. 安装与初始化把 lodop 6.057 接进三个浏览器的正确姿势2.1 解压后先分清三样东西这类控件包解压之后桌面上一般会有三样东西安装程序、免注册版文件、示例页面。安装程序适合普通办公电脑双击后向系统注册控件装完就能被网页识别。免注册版文件适合企业批量部署配合开机脚本或组策略推到几十台收银机、仓库电脑上不用每台机都点一遍下一步。示例页面是整个资源包里最重要的一份文件。我一般会先用文本编辑器打开它里面通常已经写好了对象引用和打印测试按钮直接放到内网 Web 目录里访问就能判断控件装没装好。验证方式很简单页面加载后控制台里执行LODOP.VERSION返回的字符串包含6.057就说明当前加载的正是这个版本。如果返回空或者页面直接报对象错误说明装的是别的版本或者 classid 对不上。这里要提醒一个细节资源包里的安装程序和你自己写的页面必须匹配。网页里通过object引用的 classid 在安装控件时会注册到系统里如果页面里的 classid 写的是网上随便抄的哪怕控件装了也会提示找不到对象。所以先打开包内自带的示例页面把它里面那段对象引用原样复制到你项目的页面上这能省掉后面一大半初始化报错。2.2 网页里加载控件对象的两种方式最老实的做法是在 HTML 里直接写一个object标签id 固定为 LODOP。示例页面里通常就是这种写法。代码如下body object idLODOP classidclsid:00000000-0000-0000-0000-000000000000 width0 height0/object script function createLodop() { var obj document.getElementById(LODOP); if (obj obj.VERSION) { return obj; } // 常见做法动态创建一个 object 再挂到 body 上 obj document.createElement(object); obj.setAttribute(id, LODOP); // classid 以资源包自带的说明为准不同版本有差异 obj.setAttribute(classid, clsid:00000000-0000-0000-0000-000000000000); document.body.appendChild(obj); return obj; } var LODOP createLodop(); /script /body上面的 classid 是占位示例实际值必须从资源包示例页或控件自带文档里复制。如果下载包里带有封装好的 LodopFuncs.js我一般直接引用它里头的getLodop()函数已经把创建对象、版本校验、安装引导都包好了比手工拼对象省心很多。动态创建对象的好处是页面初始化时不会被一个加载失败的插件卡住其他业务脚本照常执行等真正要打印时再调 LODOP。那个object标签的width0 height0不是随便写的。控件在页面上不需要占据可视区但必须真实存在于 DOM 中删掉标签再靠纯 JS 调用在某些 IE 内核版本里会失败。2.3 三个浏览器的兼容配置ActiveX、NPAPI 和 IE 模式6.057 是 2012 年前后的版本当时三个浏览器各自支持插件机制IE 走 ActiveXChrome 和 Firefox 走 NPAPI。放在今天这套配置思路要变。我一般这样落地浏览器6.057 时代的加载方式现在的实机状态我常用的落地策略IE / Edge IE 模式ActiveX 受信任站点内网老环境仍然可用站点加入受信任区域启用 ActiveXChromeNPAPI 插件新版已移除 NPAPI切 Edge IE 模式或用企业版管控FirefoxNPAPI 插件同样移除放弃直连统一转 IE 兼容通道内网环境里最常见的是 IE 和 Edge 的 IE 模式。要做的配置就三步打开 Internet 选项切到“安全”选择“受信任的站点”把页面地址加进去再把“自定义级别”里与 ActiveX 相关的几个选项都改成“启用”。其中最容易卡住的是“对未标记为可安全执行脚本的 ActiveX 控件初始化并执行脚本”这一项默认可能是提示不改的话控件装好了页面仍然报未安装。提示内网页面如果走 HTTP不加受信任站点会被当成低安全级别处理ActiveX 直接禁用。先加站点再刷新比反复卸载安装验签有效得多。Chrome 那边今天的策略不是去改 Chrome而是把整个应用切到 Edge 的 IE 模式。运维可以把内网页面地址配进 Edge 策略的“IE 模式站点列表”用户点开就是 IE 内核。Firefox 则不建议再花时间直接统一入口更省事。3. 用 ADD_PRINT 拼一张套打凭证坐标、单位和三种内容类型3.1 PRINT_INIT 先打底任务名和重复打印LODOP 的每次打印都以PRINT_INIT开头它负责创建一个全新的打印任务清掉上一次遗留的内容。任务名要尽量传成“单据号日期”这样的唯一字符串比如LODOP.PRINT_INIT(SO20250501-001)。如果任务名重复后一次打印会把内容追加到前一个任务里批量场景很容易把上一单的明细带到下一单。我一般会把初始化包成一个函数统一设置纸张和默认份数function createTask(taskName) { if (!LODOP) { return -1; } var ret LODOP.PRINT_INIT(taskName); if (ret 0) { return ret; } // 第二个参数 1 表示纵向后面的宽高传 0 则表示按系统驱动里的纸张定义 LODOP.SET_PRINT_PAGESIZE(1, 0, 0, A4); LODOP.SET_PRINT_COPIES(1); return 0; }PRINT_INIT返回小于 0 的值表示初始化失败最常见的原因是上一个打印任务还没结束页面就触发了新的打印。所以涉及批量打印时按钮回调里要加互锁同一时间只允许一个任务在跑。3.2 三种内容类型TEXT、HTM、IMAGE一张单据上不同区域用不同的 ADD_PRINT 方法。我的习惯是动态字段用ADD_PRINT_TEXT复杂排版用ADD_PRINT_HTM签名和底图用ADD_PRINT_IMAGE。三种方法的前四个参数完全一致上边距、左边距、宽度、高度单位都是 0.1 毫米。方法适用内容注意事项ADD_PRINT_TEXT单行文本定位最准不换行适合序号、金额字段ADD_PRINT_HTMHTML 片段支持样式和表格适合明细区域ADD_PRINT_IMAGE本地图片或 base64本地路径要加 前缀文件不存在会静默丢图示例代码LODOP.ADD_PRINT_TEXT(80, 20, 200, 20, 订单号SO20250501-001); LODOP.ADD_PRINT_HTM(110, 20, 900, 120, table border1 cellspacing0 cellpadding2 trtd品名/tdtd数量/tdtd金额/td/tr trtd钢制支架/tdtd2/tdtd560.00/td/tr /table ); LODOP.ADD_PRINT_IMAGE(240, 20, 200, 60, D:\\sign\\signature.png);ADD_PRINT_TEXT里的文本不能用\n强行换行它不是一个文本块组件换行应该拆成两行文本分两次输出或者改用ADD_PRINT_HTM包一个div。ADD_PRINT_IMAGE的前缀表示后面的路径是本地绝对路径只在控件所在的机器上有效前端页面在别的机器上访问就会取不到所以签名这类图片我尽量转成 base64 拼进去虽然占内存但不会因为路径问题打出一片空白。3.3 坐标单位0.1 毫米和那台“骗你”的屏幕LODOP 的坐标单位是 0.1 毫米所以 A4 竖版纸的宽是 2100高是 2970。设计器里拖动一个文本对象时看到的像素位置不能直接写进代码要换算成单位值。我的换算函数长这样function mmToUnit(mm) { return Math.round(mm * 10); } // 在页面顶部 35mm、左侧 5mm 处输出内容 LODOP.ADD_PRINT_TEXT(mmToUnit(35), mmToUnit(5), 300, 100, 打印内容);套打对不齐的根源往往不是坐标算错而是打印机驱动里开了“缩放以适应纸张”。驱动面板默认可能把 100% 变成“适合打印”或者 Windows 屏幕缩放影响了页面估算最后打出来整体偏右上。我一般在部署时就把驱动的缩放固定为 100%并且告诉使用的人不要改打印机属性里的纸张类型必须和代码里声明的一致。这一条能解决掉一半的“设计器里好好的打印出来歪了”的反馈。3.4 条码、份数、多联条码打印是仓库场景里的刚需。ADD_PRINT_BARCODE的第五个参数是条码类型第六个参数是内容。我的建议是内容混合大小写字母和数字时一律用128类型纯数字且位数固定可以试EAN13。LODOP.ADD_PRINT_BARCODE(320, 20, 300, 100, 128, SO20250501-001); LODOP.SET_PRINT_COPIES(3); // 三联单多联单打 3 份时SET_PRINT_COPIES让打印机把当前页整页重复输出。如果单据页里混杂了多条明细最好先把明细拼成一整页再设份数否则每页重复的是同一个整页内容拆页逻辑会乱。4. 静默打印LODOP.PRINT() 的无预览输出与打印机选择4.1 无预览不是吞掉打印任务PREVIEW()弹预览窗口给人确认PRINT()不做预览直接发送到打印机。收银小票、批量发货单这类场景用的是PRINT()。但无预览不等于没任务点击打印后任务仍然进入系统打印队列如果打印机离线任务会挂在队列里后面再打的单子全堵在一起。我见过把浏览器端 LODOP 和服务器端打印混淆的情况。LODOP 控件运行在用户浏览器的页面上必须有一个人开着这个页面才能真正触发任务。要做服务端的定时批量打印通常是另做一个自动页面放到内网一台专用电脑上定时打开并执行LODOP.PRINT()。静默打印前我至少会检测一次打印机在线状态var count LODOP.GET_PRINTER_COUNT(); if (count 1) { alert(没有检测到可用打印机请检查驱动); return; }虽然不能完全确认打印机纸张和墨盒状态但至少能拦住“驱动都丢了”的场景。4.2 打印机选择与份数参数一台电脑接了两台打印机时PRINT()默认走系统默认打印机经常打错设备。我一般用关键字匹配的方式选择打印机function pickPrinter(keyword) { var count LODOP.GET_PRINTER_COUNT(); for (var i 0; i count; i) { var name LODOP.GET_PRINTER_NAME(i); if (name.indexOf(keyword) 0) { return i; } } return -1; } var idx pickPrinter(出库); if (idx 0) { LODOP.SET_PRINTER_INDEX(idx); } LODOP.SET_PRINT_COPIES(2); LODOP.PRINT();SET_PRINTER_INDEX传 -1 表示用系统默认打印机传索引则从 0 开始。GET_PRINTER_COUNT返回的打印机数量包含虚拟打印机和已安装但未连接的驱动所以仅凭数量判断在线情况不可靠。同一台网络打印机在不同电脑上名字可能带后缀关键字匹配比硬编码索引稳定硬编码索引在打印顺序变化时会打到隔壁那台。4.3 设计器导出的语句如何安全接进生产代码LODOP 自带的设计器可以拖出套打模板并导出代码。导出的是一串ADD_PRINT_*语句我一般把它嵌进生产代码时外面套一层固定模板LODOP.PRINT_INIT(导出模板- orderNo); LODOP.SET_PRINT_PAGESIZE(1, 0, 0, A4); // 下面是从设计器导出的语句块其中变量由后台传入 LODOP.ADD_PRINT_TEXT(35, 10, 200, 30, orderNo); LODOP.ADD_PRINT_HTM(70, 10, 1000, 160, detailHtml); // 结束 LODOP.PRINT();设计器导出的坐标是固定值生产环境里不要通过 CSS 缩放去适配改位置就在设计器里拖完重新导出。后台传过来的明细 HTML 要先做转义处理否则拼接detailHtml时插入一段带引号的文本会把整个模板打崩。我在项目里会把、、转成实体字符兜底打印时再转回可见内容。5. 避坑排查6.057 用起来最常见的 5 个坑5.1 现象Chrome 打开示例页控制台报 “LODOP is not defined”原因新版 Chrome 彻底移除了 NPAPI 插件支持6.057 时代的老插件在现在的 Chrome 里根本不会被加载所以全局没有 LODOP 对象。解决不要指望在现版 Chrome 里装个插件复活它。我现在的落地方式是让整个应用走 Edge 的 IE 模式把站点地址配进策略的 IE 模式列表中用户点开就是 IE 内核LODOP 控件正常加载。如果团队确实要纯 Chrome那就换支持插件的老内核浏览器但安全补丁很难更上内网可以接受外网不建议。5.2 现象IE 里页面显示 “您还未安装控件”但明明已经装好原因控件装进了系统但浏览器的 ActiveX 安全策略把当前站点拦住了。内网 HTTP 地址默认可能被置为受限或者“对未标记为可安全执行脚本的 ActiveX 控件初始化并执行脚本”还是“禁用”。解决把页面地址加入受信任站点再在自定义级别里把所有与 ActiveX 运行相关的项改为“启用”然后重启浏览器。注意这项配置是按站点生效的换一个端口或换一条域名路径都要重新加。装完控件如果页面仍提示先看 URL 协议是不是 HTTPS受信任区域不认 IP 加端口的组合时把地址改成域名再试。5.3 现象同一张模板设计器里显示正常打印出来整体偏移右上或左下原因打印机驱动把内容按“适合页面”缩放过了或者 Windows 系统显示缩放到 125% 导致页面计算坐标时产生了偏差。我遇到的大部分套打偏移都来自这两个原因而不是 LODOP 坐标算错。解决在打印机驱动属性里把缩放固定为 100%并确认纸张类型与代码里SET_PRINT_PAGESIZE声明的一致。Windows 的显示缩放如果改不了就在浏览器兼容视图或应用页面传入一个固定 DPI 参数让页面不再跟随系统缩放。5.4 现象条码打出来很清晰但扫码枪死活扫不出原因条码类型和内容不匹配。比如内容里混了字母却选 Code39或者内容长度超过该条码类型的容量打印机能输出图案但扫码枪解码失败。解决内容含大小写字母和数字时选128类型纯数字、位数固定且不超过 13 位可以试EAN13。条码下方通常会带一串供人识别的文本把这段文本和实际内容逐字符对比能发现是内容被截断还是条码类型选错比反复换扫码枪更有效率。5.5 现象批量打印时任务重叠最后一张带出前面页的内容原因页面上短时间内多次调用了LODOP.PRINT()前一个任务还没完全从打印队列清空新任务直接追加进去或者任务名重复控件把新内容并进了旧任务里。解决打印按钮回调里加一个pending标志任务未结束前不允许再次提交每次打印前重新调用PRINT_INIT创建一个全新任务任务名带上单据号。批量列表场景还要注意不要在一个循环里连续调PRINT()改成每张单据触发一次独立任务等上一张任务回调后再打下一张。6. 一句代码验证控件状态给接手的人留一份环境探测脚本老打印模块最难排的往往是环境问题控件版本不对、打印机驱动丢失、浏览器安全策略拦截。我现在会在系统里固定放一个诊断入口执行一段探测脚本先把环境状态拉出来再看业务代码。function probeLodop() { var info { ok: false, version: unknown, printers: 0, pageOk: false }; try { var obj document.getElementById(LODOP); if (!obj) { obj LODOP; } if (obj) { info.ok true; info.version obj.VERSION || unknown; info.printers obj.GET_PRINTER_COUNT() || 0; info.pageOk obj.PRINT_INIT(probe) 0; if (info.pageOk) { obj.PRINT_SETUP(); // 主动弹一次打印设置验证驱动链路 } } } catch (e) { info.err e.message; } return info; }返回结果里version不是 6.057就说明加载的不是资源包里那版控件优先重装而不是查代码。printers为 0说明系统里没有可用打印机或驱动已经损坏直接去修驱动不用在页面排版里找原因。pageOk为 false说明对象存在但打印任务初始化失败通常是上一个任务还卡在队列里重启浏览器就能恢复。我从那以后每次接手老打印项目都会先强制跑一遍这段探测脚本把环境问题从业务逻辑里剥出去再改代码省下不少开会解释的时间。希望帮到你。本文还有配套的精品资源点击获取