python+html实现本地打印机转成互联网共享打印机代码

代码语言:python

所属分类:其他

代码描述:python+html实现本地打印机转成互联网共享打印机代码

代码标签: python html 本地 打印机 互联网 共享 打印机 代码

下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开

#!/usr/bin/env python3
"""
╔══════════════════════════════════════════╗
║       远程打印 Web 服务                    ║
║  登录 → 上传文件 → 选择打印机 → 打印       ║
╠══════════════════════════════════════════╣
║  安装依赖:                                ║
║    pip install flask pillow              ║
║  Windows额外(打印机枚举):                  ║
║    pip install pywin32                   ║
║                                          ║
║  运行: python app.py                     ║
║  访问: http://localhost:5000             ║
║  账号: admin / admin123                  ║
╚══════════════════════════════════════════╝
"""

import os
import sys
import uuid
import json
import subprocess
import tempfile
import time
import threading
from functools import wraps
from datetime import datetime

from flask import (
    Flask, request, redirect, url_for,
    render_template_string, session, jsonify,
    send_from_directory, send_file
)
from werkzeug.utils import secure_filename

# ========================= 配置 =========================
HOST = '0.0.0.0'
PORT = 5000

UPLOAD_FOLDER = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'uploads')
ALLOWED_IMAGE = {'png', 'jpg', 'jpeg', 'gif', 'bmp', 'tiff', 'webp'}
ALLOWED_DOC = {'pdf', 'txt', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'rtf'}
ALLOWED_EXT = ALLOWED_IMAGE | ALLOWED_DOC
MAX_SIZE = 50 * 1024 * 1024  # 50MB

USERS = {
    'admin': {'password': 'admin123', 'name': '管理员'},
    'user':  {'password': 'user123',  'name': '普通用户'},
}

os.makedirs(UPLOAD_FOLDER, exist_ok=True)

app = Flask(__name__)
app.secret_key = 'remote-print-server-secret-key-2024'
app.config['MAX_CONTENT_LENGTH'] = MAX_SIZE

# 内存文件存储
file_store = {}
print_history = []

# ========================= 装饰器 =========================
def login_required(f):
    @wraps(f)
    def decorated(*args, **kwargs):
        if 'user' not in session:
            if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
                return jsonify({'ok': False, 'msg': '请先登录'}), 401
            return redirect(url_for('login'))
        return f(*args, **kwargs)
    return decorated

# ========================= 打印机操作 =========================
def get_printers():
    """获取系统打印机列表"""
    printers = []
    if sys.platform == 'win32':
        try:
            import win32print
            default = win32print.GetDefaultPrinter()
            for p in win32print.EnumPrinters(win32print.PRINTER_ENUM_LOCAL | win32print.PRINTER_ENUM_CONNECTIONS):
                name = p[2]
                printers.append({'name': name, 'default': name == default, 'status': '就绪'})
        except ImportError:
            pass
        if not printers:
            try:
                r = subprocess.run(
                    ['powershell', '-Command',
                     "Get-Printer | Select-Object Name,PrinterStatus | ConvertTo-Json -Compress"],
                    capture_output=True, text=True, timeout=10
                )
                if r.stdout.strip():
                    data = json.loads(r.stdout)
                    if isinstance(data, dict):
                        data = [data]
                    status_map = {0: '就绪', 1: '暂停', 2: '错误', 3: '删除中', 4: '离线'}
                    for d in data:
                        printers.append({
                            'name': d.get('Name', ''),
                            'default': False,
                            'status': status_map.get(d.get('PrinterStatus', 0), '未知')
                        })
            except Exception:
                pass
    else:
        try:
            r = subprocess.run(['lpstat', '-p', '-d'], capture_output=True, text=True, timeout=10)
            default_name = ''
            for line in r.stdout.split('\n'):
                if 'system default destination:' in line:
                    default_name = line.split(':')[-1].strip()
                elif line.startswith('printer'):
                    name = line.split()[1]
                    printers.append({'name': name, 'default': name == default_name, 'status': '就绪'})
        except Exception:
            pass

    if not printers:
        printers.append({'name': '默认打印机', 'default': True, 'status': '就绪'})
    return printers


def do_print(filepath, printer_name, copies=1):
    """执行打印任务"""
    if not os.path.exists(filepath):
        return False, '文件不存在'

    try:
        if sys.platform == 'win32':
            return _print_windows(filepath, printer_name, copies)
        else:
            return _print_linux(filepath, printer_name, copies)
    except Exception as e:
        return False, f'打印异常: {str(e)}'


def _print_windows(filepath, printer_name, copies):
    # 方式1: win32api ShellExecute
    try:
        import win32api
        for _ in range(copies):
            win32api.ShellExecute(
                0, "printto", filepath,
                f'"{printer_name}"', os.path.dirname(filepath), 0
            )
        return True, f'已发送 {copies} 份到 {printer_name}'
    except Exception:
        pass

    # 方式2: PowerShell
    try:
        ps = f'''
        $file = "{filepath}"
        $printer = "{printer_name}"
        for ($i=1; $i -le {copies}; $i++) {{
            Start-Process -FilePath $file -Verb PrintTo -ArgumentList $printer
        }}
        '''
        r = subprocess.run(
            ['powershell', '-Command', ps],
            capture_output=True, text=True, timeout=60
        )
        if r.returncode == 0:
            return True, f'已发送 {copies} 份到 {printer_name}'
        return False, r.stderr.strip() or 'PowerShell 打印失败'
    except Exception as e:
        return False, str(e)


def _print_linux(filepath, printer_name, copies):
    cmd = ['lp']
    if printer_name and printer_name not in ('默认打印机', 'Default'):
        cmd += ['-d', printer_name]
    cmd += ['-n', str(copies), filepath]
    r = subprocess.run(cmd, capture_output=True, text=True, timeout=60)
    if r.returncode == 0:
        return True, f'已发送 {copies} 份到 {printer_name}'
    return False, r.std.........完整代码请登录后点击上方下载按钮下载查看

网友评论0