You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

求助:win32print打印PDF文件出现空白,如何修复?

修复空白PDF打印问题的解决方案

我来帮你搞定这个问题!你得到空白PDF的核心原因是:你使用了RAW打印模式,但Microsoft Print to PDF并不支持直接接收原始PDF字节流——它需要的是Windows打印系统能识别的打印指令(比如EMF、PostScript这类格式),而不是PDF文件本身的二进制数据。下面是两种可靠的修复方案,都保留了你需要的打印状态检查功能:

方案一:使用Ghostscript转换PDF为打印机兼容格式(推荐)

既然你允许使用Ghostscript,这是最稳定的方案。Ghostscript可以把PDF文件转换成Windows打印队列能处理的数据流,这样Microsoft Print to PDF就能正确生成有内容的PDF了。

步骤1:安装Ghostscript

先下载安装Ghostscript(注意选择对应你系统的版本,32/64位),安装后记得把Ghostscript的bin目录添加到系统环境变量PATH里,或者在代码里直接指定gswin64c.exe(或gswin32c.exe)的完整路径。

步骤2:修改后的代码

from win32 import win32print
import subprocess

def get_pdf_print_stream(pdf_path):
    # 用Ghostscript把PDF转换成打印机兼容的数据流
    gs_cmd = [
        "gswin64c.exe",  # 如果是32位系统换成gswin32c.exe
        "-dNOPAUSE",
        "-dBATCH",
        "-dSAFER",
        "-sDEVICE=mswinpr2",  # 针对Windows打印机的专用设备
        "-sOutputFile=%stdout%",  # 输出到标准输出
        pdf_path
    ]
    result = subprocess.run(gs_cmd, capture_output=True, check=True)
    return result.stdout

if __name__ == "__main__":
    printer_name = "Microsoft Print to PDF"
    pdf_to_print = "to_print\\document1.pdf"
    print(f"Printer: {printer_name}")
    
    hPrinter = win32print.OpenPrinter(printer_name)
    try:
        # 这里的文档名是最终输出的PDF文件名
        hJob = win32print.StartDocPrinter(hPrinter, 1, ("output.pdf", None, "RAW"))
        try:
            print_stream = get_pdf_print_stream(pdf_to_print)
            win32print.StartPagePrinter(hPrinter)
            win32print.WritePrinter(hPrinter, print_stream)
            win32print.EndPagePrinter(hPrinter)
            
            # 检查打印状态
            job_info = win32print.GetJob(hPrinter, hJob, 2)
            print(f"Print Job Status: {job_info['Status']}")
            if job_info['Status'] == win32print.JOB_STATUS_PRINTING or job_info['Status'] == win32print.JOB_STATUS_COMPLETED:
                print("Print job is successful!")
            else:
                print(f"Print job may have issues. Status code: {job_info['Status']}")
        finally:
            win32print.EndDocPrinter(hPrinter)
    finally:
        print(f"Print Job ID: {hJob}")
        win32print.ClosePrinter(hPrinter)

代码说明

  • get_pdf_print_stream函数:调用Ghostscript把目标PDF转换成打印机能识别的数据流,mswinpr2是Ghostscript针对Windows打印系统的专用设备。
  • 保留了所有原有的打印状态检查逻辑:通过GetJob获取任务状态,判断打印是否成功。
  • StartDocPrinter里的第一个参数是最终输出的PDF文件名(Microsoft Print to PDF会用这个名称生成文件)。

方案二:不使用Ghostscript,改用EMF格式(限简单内容)

如果不想依赖Ghostscript,你可以通过Windows的设备上下文(DC)来绘制内容,但这种方式更适合简单的文本或图形,复杂PDF还是推荐方案一。核心思路如下:

  • 创建打印机DC,用pywin32win32uiwin32gdi等模块在DC上绘制PDF内容(需要额外处理PDF渲染逻辑)。
  • 将DC的内容发送给打印机,这种方式不需要RAW模式,能被Microsoft Print to PDF正确解析。

为什么原代码会生成空白PDF?

原代码中StartDocPrinter的第三个参数是"RAW",这意味着你直接把PDF的二进制字节流发送给打印机。但Microsoft Print to PDF是虚拟打印机,它无法直接解析原始PDF文件,只能接收Windows打印系统的标准指令(比如EMF),所以它无法识别你发送的PDF字节,最终生成空白文件。

内容的提问来源于stack exchange,提问作者xralf

火山引擎 最新活动