# 内网打印 **Repository Path**: it155/intranet-printing ## Basic Information - **Project Name**: 内网打印 - **Description**: 内网打印内网打印内网打印 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 4 - **Created**: 2026-09-23 - **Last Updated**: 2026-09-23 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 内网打印服务 · 使用说明文档 > 适用版本:Python 内网静默打印服务端(Flask + PyInstaller 打包) > 文档整理日期:2026-09-22 > 适用平台:**仅 Windows 10 / 11**(依赖系统打印接口与 COM 组件) --- ## 1. 软件概述 ### 1.1 核心功能与用途 本软件是一个**局域网内网文件打印服务**。它在运行机器上以后台托盘程序常驻,提供网页管理端;内网其他电脑通过浏览器访问该服务地址,即可将本地文件**直接静默发送到本机连接的打印机**,无需在每台电脑上安装打印机驱动或办公软件。 核心能力: - **多格式支持**:PDF、图片、Office 文档、WPS 文档、纯文本均可在网页端一键上传并打印(详见 1.3)。 - **网页预览**:上传后可先查看文档缩略图,确认版式与页码无误再打印。 - **后台队列**:打印任务进入队列异步执行,前端实时显示任务状态(排队中 / 打印中 / 已完成 / 失败)。 - **权限与审计**:支持账号登录、管理员/普通用户角色分离,所有打印与登录行为记入审计日志。 - **静默交付**:通过系统打印接口(win32print / COM)将文件送入打印机,不弹任何窗口。 ### 1.2 典型使用场景 - 办公室公用电脑连接着一台打印机,同事只需在浏览器打开服务地址即可打印自己的文件。 - 服务器/工控机连着标签打印机或票据打印机,通过网页下发打印任务。 - 运维人员集中管理多台打印机的打印记录与权限。 ### 1.3 支持的文件格式(共 20 种) | 类别 | 扩展名 | 说明 | |------|--------|------| | PDF | `.pdf` | 原生支持 | | 图片 | `.jpg` `.jpeg` `.png` `.bmp` `.gif` `.tiff` `.webp` | 7 种常见位图 | | Office(新版) | `.docx` `.xlsx` `.pptx` | 需本机安装 Microsoft Office 才能预览/打印 | | Office(旧版) | `.doc` `.xls` `.ppt` | 需本机安装 Microsoft Office | | WPS | `.wps` `.et` `.dps` | 需本机安装 WPS Office 才能预览/打印 | | 文本 | `.txt` `.md` `.log` | 直接渲染文本预览 | > 表格、文字、演示三类 WPS 格式(`.et`/`.wps`/`.dps`)和旧版 Office(`.doc`/`.xls`/`.ppt`)的**预览与打印依赖本机已安装对应办公软件**,否则会报错提示「请先安装」。 --- ## 2. 安装与部署 ### 2.1 目录结构(源码形态) ``` py_print_server/ ├── tray_app.py # 托盘启动入口(双击/运行即启动服务) ├── app.py # Flask 主程序(API 与网页) ├── print_engine.py # 后台静默打印引擎(win32print / GDI) ├── queue_manager.py # 打印任务队列(后台 worker + 写打印日志) ├── preview_service.py # 文档预览渲染(缓存/导出调度/缩略图) ├── print_layout.py # 多页(n-up)/小册子(booklet)页面重排合成 ├── print_office.py # Office → PDF(依赖 MS Office) ├── print_wps.py # WPS → PDF(依赖 WPS Office) ├── print_fit.py # 页面缩放计算(适合页面 / 仅缩小) ├── paper_apply.py # 选定纸张尺寸写入打印机 DEVMODE ├── printer_manager.py # 打印机枚举与能力/方向/双面映射 ├── auth.py # 账号、会话与配置(config.json) ├── audit.py # 审计日志(管理操作) ├── logger.py # 打印日志(记录每次打印) ├── logging_setup.py # 程序运行期日志配置 ├── control_panel.py # 独立 Tkinter 桌面控制面板(本地运维) ├── dialog_helper.py # 原生对话框辅助(ctypes / PowerShell) ├── config.json # 运行时配置(首次启动自动生成,非手写源码) ├── templates/index.html # 网页前端(单页) ├── build.spec # PyInstaller 打包配置 ``` > 各模块的详细职责、相对路径与架构分层,见 **第 8 节「核心源代码清单与模块职责(维护者参考)」**。 ### 2.2 在开发机/本机以源码运行 要求:Windows + Python 3.13 + 已建好虚拟环境 `venv/`。 ```bash cd py_print_server venv\Scripts\python.exe app.py # 默认端口 5000 venv\Scripts\python.exe app.py --port 8080 # 指定端口(覆盖 config.json) ``` 启动后访问 `http://127.0.0.1:5000`。此方式仅供开发与调试,**日常使用请改用托盘 EXE**。 ### 2.3 打包为免 Python 的 EXE(在开发机执行一次) 项目已提供打包脚本 `打包为单文件EXE.bat`。双击运行即可生成 `dist\tray_app\` 目录(内含 `tray_app.exe` 与 `_internal\` 依赖)。 > 打包细节(维护人员参考):使用 PyInstaller onedir 模式;若需重新打包,先把旧的 `dist\tray_app` 移走(**移动,不要直接删除**),再运行 `venv\Scripts\python.exe -m PyInstaller build.spec --noconfirm --distpath dist --workpath build_run_<时间戳>`。 ### 2.4 部署到目标机(免 Python) 1. 将整个 `dist\tray_app\` 文件夹复制到目标 Windows 电脑的任意位置(如 `D:\PrintServer\`)。 2. 双击 `tray_app.exe` 启动。首次启动会在同目录生成 `config.json`、`uploads\`、`preview_cache\`、`logs\`。 3. 目标机需满足: - 已连接要使用的打印机(驱动正常)。 - 若要打印 **PDF**:本机需安装 **SumatraPDF** 或 **Adobe Reader/Acrobat**(用于静默下发 PDF)。 - 若要打印 **Office/WPS 文档**:本机需安装对应 **Microsoft Office / WPS Office**。 > ⚠️ `tray_app.exe` 与 `_internal\` 必须放在**同一目录**,且运行时该目录需有**写入权限**(程序会写配置与临时文件)。不要只把 `tray_app.exe` 单独剪切出来。 --- ## 3. 启动与基本操作 ### 3.1 启动与托盘图标 - 双击 `tray_app.exe`(或开发机的 `tray_app.py`)即启动。 - 启动成功后,Windows 任务栏右侧出现一个**蓝色打印机图标**(系统托盘)。 - 服务绑定在 `0.0.0.0:<端口>`,即本机及同网段其他电脑均可访问。 ### 3.2 托盘右键菜单 | 菜单项 | 作用 | |--------|------| | **服务地址: http://IP:端口** | 显示当前访问地址(点击即在浏览器打开) | | **当前IP: x.x.x.x (DHCP/静态)** | 显示本机当前 IP 与网络模式 | | **更改端口...** | 弹窗输入新端口(1024–65535),保存后自动重启服务 | | **开机自动启动** | 勾选/取消开机自启(写入注册表 `HKCU\...\Run`) | | **重启服务器** | 用当前端口重启服务 | | **退出** | 彻底退出(结束托盘与后台 Flask 进程) | ### 3.3 打开管理页面 - 在本机或其它同网段电脑浏览器输入托盘菜单里的「服务地址」(如 `http://192.168.1.50:5000`)。 - 首页即打印界面;右上角「管理后台」入口**始终可见**,点击后按要求登录。 > 🔒 **单实例限制**:同一台机器**不能同时运行两个** `tray_app.exe`,重复启动会被阻止并提示「已在运行中」。 --- ## 4. 功能模块操作指引 ### 4.1 打印(核心功能) #### 方式 A:上传后直接打印 1. 在首页选择**文件**(可多选)。 2. 在「打印机」下拉中选择目标打印机(列表来自本机已安装打印机)。 3. 设置参数:份数、纸张(A4/A5/…)、方向(纵向/横向)、单/双面、分辨率、缩放模式(适合页面 / 仅缩小)、页码范围。 4. 点击「打印」,任务进入后台队列,页面下方显示状态。 #### 方式 B:先预览再打印 1. 上传文件后点击「预览」,查看文档缩略图。 2. 确认无误后,在预览界面点「打印此文件」,复用已上传文件直接入队。 #### 4.1.1 打印参数说明 | 参数 | 取值 | 说明 | |------|------|------| | 打印机 | 下拉选择 | **必填**;列表来自系统已安装打印机 | | 份数 | 整数 | 默认 1 | | 纸张 | A4 / A5 / Letter … | 默认 A4 | | 方向 | 纵向 / 横向 | 默认纵向 | | 双面 | 单面 / 双面 | 默认单面;需打印机支持 | | 缩放 | 适合页面 / 仅缩小 | 「适合页面」会把小页面放大铺满 | | 页码范围 | 如 `1-5`、`1,3,5`、`7` | 留空 = 全部页 | ### 4.2 打印预览 - 预览在网页弹窗中渲染文档缩略图。 - **限制**:最多渲染前 **6 页**;单张缩略图宽度上限 **900 像素**;预览源文件大小上限 **20 MB**(超过则提示超限)。 - Office / WPS 文档预览会先由本机 Office/WPS 转换为 PDF 再渲染,因此**首次预览该类文件稍慢**(需启动办公软件)。 - 个别 pptx 若含受限字体/损坏对象,PowerPoint 会拒绝导出,此时预览失败但**仍可直接打印**(见 6.3)。 ### 4.3 打印队列 - 首页/队列页实时展示任务:排队中 → 打印中 → 已完成 / 失败。 - 失败任务可查看错误原因;可手动取消队列中的任务。 - 后台采用异步队列,大量连续打印不会阻塞网页。 ### 4.4 管理后台 > 入口:首页右上角「管理后台」(始终可见)。需管理员账号登录。 #### 4.4.1 首次登录与改密 - **默认管理员账号:`admin` 默认密码:`admin123`** - ⚠️ **首次使用后请立即修改密码**(见 4.4.4)。若关闭全局认证(见 4.4.2),管理入口仍可点开但需管理员登录。 #### 4.4.2 系统配置(可在网页调整) | 配置项 | 默认值 | 说明 | |--------|--------|------| | 端口 port | 5000 | 修改后需重启服务(托盘菜单「重启服务器」或改端口) | | 启用认证 auth_enabled | 开启 | 关闭后允许匿名访问与打印(仅限内网可信环境) | | 开机自启 autostart | 关闭 | 等价于托盘「开机自动启动」 | | 上传自动删除 auto_delete_minutes | 5 | 上传文件在 N 分钟后自动清理(0 = 不清理) | | 上传大小上限 max_upload_size_mb | 5 | 范围 1–512 MB;超过被拒 | | 打印日志保留天数 | 0 | 0 = 永久保留 | | 审计日志保留天数 | 0 | 0 = 永久保留 | | 同名去重 dedup_uploads | 开启 | 开启后同名文件自动追加 `_1/_2` 序号 | > 配置保存在 `tray_app.exe` 同目录的 `config.json`,可直接停止程序后手动编辑,再重启生效。 #### 4.4.3 用户管理(管理员) - 创建用户(用户名 + 密码 + 角色 `admin`/`user`)。 - 修改用户密码/角色、删除用户。 - **`admin` 账户不可被删除**。 - 普通用户(`user`)只能打印与查看自己的任务;管理员可查看全部日志与用户。 #### 4.4.4 密码管理 - 管理员可「修改自己的密码」。 - 管理员可「重置任意用户密码」(被重置用户需重新登录)。 - 密码长度至少 6 位,使用 bcrypt-sha256 哈希存储(明文不会写入磁盘)。 #### 4.4.5 打印日志 - 记录每次打印:谁、哪台电脑(IP/主机名)、文件名、时间、参数。 - 支持按条件筛选、导出、按保留天数清理、一键清空。 #### 4.4.6 审计日志 - 记录管理类操作:管理员登录、创建/修改/删除用户、改密、重置密码、清空日志等。 - 支持筛选、导出、清空。 ### 4.5 端口与开机自启 - 改端口:托盘菜单「更改端口...」→ 输入 1024–65535 → 自动重启。 - 开机自启:托盘菜单勾选「开机自动启动」。 - 若端口被占用,启动会失败,请换端口或释放占用进程。 --- ## 5. 常见使用场景示例 **场景 1:同事打印自己的 PDF** > 同事在浏览器打开 `http://192.168.1.50:5000` → 选 PDF → 选公用打印机 → 设份数 2 → 打印。完成后在队列看到「已完成」。 **场景 2:先预览确认再打印 Word** > 上传 `.docx` → 点「预览」确认版式 → 「打印此文件」→ 选打印机。若本机装了 MS Office,预览会显示文档内容。 **场景 3:批量打印多份票据** > 一次选择多个文件 → 逐个或统一设置纸张/份数 → 全部入队,后台依次打印。 **场景 4:限制内网匿名打印** > 管理后台保持「启用认证」开启 → 普通同事用分配的 `user` 账号登录后才能打印;管理员用 `admin` 查看全部打印记录。 **场景 5:办公室下班后无人值守** > 勾选「开机自动启动」→ 服务器重启后自动运行;上传文件 5 分钟后自动清理,不占磁盘。 --- ## 6. 注意事项、限制与易错点 ### 6.1 注意事项 1. **默认密码必须改**:出厂 `admin/admin123` 仅为初始值,生产环境请立即修改,避免任意内网用户取得管理员权限。 2. **PDF 打印依赖阅读器**:本机需安装 **SumatraPDF** 或 **Adobe Reader/Acrobat**。若两者皆无,PDF 打印会报「未找到 PDF 静默打印工具」。 3. **Office/WPS 预览与打印依赖本机软件**:打印 `.docx/.xlsx/.pptx/.doc/.xls/.ppt` 需装 Microsoft Office;打印 `.wps/.et/.dps` 需装 WPS Office。未安装会在提交时直接报错提示。 4. **配置文件旁置**:`config.json`、上传目录 `uploads\`、预览缓存 `preview_cache\`、日志 `logs\` 都生成在 `tray_app.exe` 同级目录,迁移时连同 `_internal\` 一起拷贝。 5. **内存占用**:闲时约 50 MB、CPU 近 0%;持续高负载压力测试峰值约 190 MB / 23%(单核)。日常单文件打印约 60–80 MB,无压力。 6. **安全边界**:服务监听 `0.0.0.0`,即同网段均可访问。**关闭认证(auth_enabled=false)将允许匿名打印**,仅建议在可信内网使用,切勿在公网暴露该端口。 ### 6.2 限制条件 | 限制项 | 说明 | |--------|------| | 平台 | 仅 Windows 10/11,不支持 macOS / Linux | | 单实例 | 同机不能同时运行两个实例 | | 预览页数 | 最多渲染前 6 页 | | 预览文件大小 | 源文件 ≤ 20 MB | | 上传大小 | 默认 ≤ 5 MB(后台可调至 512 MB) | | 旧版 Office / WPS | 预览与打印需本机有对应办公软件;否则只能尝试直接打印 | | 双面对齐 | 依赖打印机硬件是否支持双面 | | 个别 pptx | 含受限字体/损坏对象的文件,PowerPoint 自身拒绝导出预览,但可直接打印 | ### 6.3 易错点提醒 - ❌ **只拷贝 `tray_app.exe` 不拷 `_internal\`** → 程序无法启动。务必整目录部署。 - ❌ **目标机没装 SumatraPDF/Adobe** → PDF 打印失败。请先安装其一。 - ❌ **`dist\tray_app` 被占用时重新打包** → 先结束残留 `tray_app.exe` 进程再打包(否则文件锁导致打包异常)。 - ❌ **改了前端 `index.html` 后不重启** → 修改网页模板后必须**完全退出并重新启动**服务(托盘「退出」再双击)才能生效。 - ❌ **端口被占用仍启动** → 换端口或释放占用进程;不要强行重复启动。 - ⚠️ **预览失败 ≠ 不能打印**:Office/WPS 个别文件预览转换失败时,提示「该文件仍可直接打印,无需预览」,直接走打印流程即可。 - ⚠️ **上传文件会自动删除**:默认 5 分钟后清理(可在后台调整),重要文件请先自行留存原件。 - ⚠️ **网络环境变化**:本机 IP 因 DHCP 改变后,托盘菜单「服务地址」会显示新 IP;同事需用新地址访问。 --- ## 7. 故障排查速查 | 现象 | 可能原因 | 处理 | |------|----------|------| | 双击 EXE 无反应 / 启动报错 | 缺 `_internal\` 目录或目录无写权限 | 整目录拷贝;换有写权限的路径 | | 浏览器打不开服务地址 | 服务未启动 / 端口错 / 防火墙 | 看托盘图标是否在;确认 IP:端口;放行防火墙 | | PDF 打印报「未找到打印工具」 | 未装 SumatraPDF/Adobe | 安装其一后重试 | | WPS 文件报「未检测到 WPS」 | 本机未装 WPS Office | 安装 WPS 后重试 | | Office 预览慢/失败 | 未装 Office 或文件异常 | 安装 Office;个别损坏文件直接打印 | | 上传被拒「文件过大」 | 超过上传上限 | 后台调大 `max_upload_size_mb` 或压缩文件 | | 预览提示超过 20MB | 源文件过大 | 拆分或缩减后再上传 | | 重复启动被拦截 | 已有实例运行 | 托盘「退出」旧实例后再启动 | | 改端口后页面打不开 | 服务重启中 | 稍等数秒,用新端口地址访问 | --- ## 8. 核心源代码清单与模块职责(维护者参考) 本节面向**二次开发 / 维护人员**,列出构成产品运行能力的核心源码文件,按架构层次组织,并说明「核心源码」的判定标准及其与辅助文件的区别。 ### 8.1 架构分层与核心文件 #### 第 0 层 · 启动与入口 | 相对路径 | 主要职能 | |----------|----------| | `tray_app.py` | Windows 系统托盘启动器。常驻托盘、单实例保护、端口设置菜单;EXE 冻结态下的子命令分发(`--export-office` / `--export-wps` / `--export-preview-*` / `--dialog`),使 Office/WPS 导出与对话框能复用同一个 exe 运行。 | | `control_panel.py` | 独立的 Tkinter 桌面「控制面板」GUI,供本机运维时查看/配置本服务(非网页端)。 | | `dialog_helper.py` | 原生对话框辅助:ctypes `MessageBoxW` + PowerShell InputBox,被 `tray_app.py` 在冻结态调用以弹出提示/输入端口,避免依赖 tkinter。 | #### 第 1 层 · Web 服务与 API | 相对路径 | 主要职能 | |----------|----------| | `app.py` | Flask 主程序。承载全部 HTTP API 与网页路由、文件上传处理、打印/预览任务提交入口、HTTP Basic 鉴权装饰器(`@admin_required` 等)、客户端 IP/主机名捕获。是前后端交互的总入口。 | #### 第 2 层 · 业务编排 | 相对路径 | 主要职能 | |----------|----------| | `queue_manager.py` | 线程安全的打印队列(`PrintQueue` / `QueueItem`)。后台 worker 依次取出任务调用打印引擎;维护任务状态(等待中/打印中/完成/失败);**打印完成后由 `resolve_effective_duplex` 计算实际生效双面并写入打印日志**(排版会强制改双面,日志须与打印一致)。 | | `preview_service.py` | 文档预览服务。上传文件缓存、调度 Office/WPS 导出子进程、缩略图渲染、LRU 图像缓存与内存压力控制;预览缓存键包含全部影响版面的参数(方向、页码范围等)。 | #### 第 3 层 · 打印引擎与格式转换 | 相对路径 | 主要职能 | |----------|----------| | `print_engine.py` | `PrintEngine`:按文件格式分发到 GDI / Office / WPS 打印路径;多页(n-up)与小册子(booklet)排版打印(`_print_with_layout`);模块级 `resolve_effective_duplex()` 作为双面语义的**单一真相源**,被打印与日志共用。 | | `print_office.py` | 隔离的 Office→PDF 导出与打印(依赖本机 Microsoft Office,COM)。作为冻结子命令被 `tray_app` 重新派发执行。 | | `print_wps.py` | 隔离的 WPS→PDF 导出与打印(依赖本机 WPS Office)。同上,作为子命令执行。 | | `print_layout.py` | 页面重排合成核心:`compose()` 实现多页每页多张(n-up)与折手重排(booklet),处理页码顺序、装订边、页边距、纸张方向。 | | `print_fit.py` | 页面缩放计算:解析「适合页面 / 仅缩小」模式,给出纸张像素尺寸与缩放比例,供 GDI 输出使用。 | | `paper_apply.py` | 将选定的纸张尺寸(含自定义/用户定义表单名)写入打印机 `DEVMODE`,使非标准纸型可下发。 | | `printer_manager.py` | `PrinterManager`:枚举本机已安装打印机、探测能力(是否支持双面/自定义纸型),并提供方向、双面、纸张→`DEVMODE` 常量(`map_orientation` / `map_duplex` / `map_paper_size`)的映射。 | #### 第 4 层 · 配置、鉴权与日志 | 相对路径 | 主要职能 | |----------|----------| | `auth.py` | 账号与会话管理:用户读写、`bcrypt-sha256` 口令校验、角色(`admin`/`user`)、登录态;同时负责 `config.json` 的读写(`load_config` / `save_config`)。 | | `audit.py` | `AuditLogger`:记录管理类操作(登录、增删改用户、改密、重置密码、清空日志等)的审计日志。 | | `logger.py` | `PrintLogger`:打印记录持久化(谁、哪台机、文件名、时间、参数、排版字段、状态),支持导出与清理。 | | `logging_setup.py` | 程序运行期 `logging` 配置(集中分级日志输出,区别于业务日志 `logger.py`)。 | #### 前端 | 相对路径 | 主要职能 | |----------|----------| | `templates/index.html` | 单页 Web 前端(HTML/CSS/JS)。打印、预览、队列、管理后台的全部交互均在此实现;被 `build.spec` 作为 `datas` 打进 EXE,运行时读包内模板。 | > **说明**:`config.json`、`uploads\`、`preview_cache\`、`logs\` 是**运行时生成的数据/配置**,不是源码;修改网页必须重建 EXE。