打印

本指南介绍如何使用打印(Printing)API。

概述 

网页可以通过以下方式之一进行打印:

  1. 使用 window.print() JavaScript 函数。该函数可以在网页的 JavaScript 代码中调用。

  2. 使用 Fuzio API 的 Frame.print() 方法。该方法会请求打印指定的。如果你需要打印整个页面,应在主帧中调用 print() 方法。例如:

    Java
    Kotlin
    browser.mainFrame().ifPresent(Frame::print);
    
    browser.mainFrame?.print()
    

网页不会立即开始打印。系统会调用 PrintCallback 来决定浏览器应如何处理打印请求。默认情况下,所有打印请求都会被取消。

打印预览 

要允许打印请求并显示打印预览(Print Preview) 对话框,请使用以下代码:

Java
Kotlin
browser.set(PrintCallback.class, (params, tell) -> tell.showPrintPreview());
browser.register(PrintCallback { params, tell ->
    tell.showPrintPreview()
})

在打印预览对话框中,你可以选择所需的打印选项:

打印预览

配置设置 

使用以下代码通知浏览器继续打印:

Java
Kotlin
browser.set(PrintCallback.class, (params, tell) -> tell.print());
browser.register(PrintCallback { params, tell ->
    tell.print()
})

之后,会触发 PrintHtmlCallbackPrintPdfCallback ,以便你配置打印设置。触发哪个回调取决于浏览器当前加载的内容类型:PrintHtmlCallback 用于 HTML 内容,PrintPdfCallback 用于 PDF 内容。

下面我们来看看如何使用这些回调。

第 1 步:选择打印机 

首先,你需要选择要使用的打印机。打印机分为两类:PdfPrinterSystemPrinterPdfPrinter 相当于打印预览对话框中的 Save as PDFSystemPrinter 类型表示系统中安装的打印机,可以是虚拟的或物理的。回调参数提供了可用打印机的列表。您可以检索 PdfPrinter、默认系统打印机,或从系统打印机中选择一个:

Java
Kotlin
browser.set(PrintHtmlCallback.class, (params, tell) -> {
    // PDF 打印机始终可用。
    var pdfPrinter = params.printers().pdfPrinter();

    // 默认打印机是可选的。
    var defaultPrinter = params.printers()
            .defaultPrinter()
            .orElseThrow(() -> new IllegalStateException("The default printer is not found."));

    // 按名称查找系统打印机。
    var systemPrinter = params.printers()
            .list()
            .stream()
            .filter(printer -> printer.deviceName().equals("Microsoft XPS Document Writer"))
            .findFirst()
            .orElseThrow(() -> new IllegalStateException("The printer is not found."));
});
browser.register(PrintHtmlCallback { params, tell ->
    // PDF 打印机始终可用。
    val pdfPrinter = params.printers.pdf

    // 默认打印机是可选的。
    val defaultPrinter = params.printers.default!!

    // 按名称查找系统打印机。
    val systemPrinter = params.printers.list()
        .firstOrNull { it.deviceName() == "Microsoft XPS Document Writer" }
        ?: throw IllegalStateException("The printer is not found.")
})

第 2 步:配置设置 

每个打印机都对应一个 PrintSettings 类型,用于定义当前上下文下该打印机可用的打印设置。每个打印机都包含一个 PrintJob,表示当前打印操作。打印设置会应用到某个打印作业上:

Java
Kotlin
var printer = params.printers()
        .defaultPrinter()
        .orElseThrow(IllegalStateException::new);
var printJob = printer.printJob();
printJob.settings()
        .header("<span style='font-size: 12px;'>Page header:</span>"
                + "<span class='title'></span>")
        .footer("<span style='font-size: 12px;'>Page footer:</span>"
                + "<span class='pageNumber'></span>")
        .paperSize(ISO_A4)
        .colorModel(COLOR)
        .enablePrintingBackgrounds()
        .disablePrintingHeaderFooter()
        .orientation(PORTRAIT)
        .apply();
val printer = params.printers.default!!
val printJob = printer.job
printJob.settings()
    .header(
        "<span style='font-size: 12px;'>Page header:</span>"
                + "<span class='title'></span>"
    )
    .footer(
        "<span style='font-size: 12px;'>Page footer:</span>"
                + "<span class='pageNumber'></span>"
    )
    .paperSize(ISO_A4)
    .colorModel(COLOR)
    .enablePrintingBackgrounds()
    .disablePrintingHeaderFooter()
    .orientation(PORTRAIT)
    .apply()

调用 apply() 会应用已配置的设置,并重新生成打印预览文档,之后该文档会被发送到打印机进行打印。

设置应用后,实际需要打印的页数可能会发生变化。你可以监听 PageCountUpdated 事件来获取页数,并在需要时调整设置:

Java
Kotlin
printJob.on(PageCountUpdated.class, params -> {
    var pageCount = params.pageCount();
    var pageRange = PageRange.of(1, pageCount);
    printJob.settings().pageRanges(pageRange).apply();
});
printJob.subscribe<PageCountUpdated> { event ->
    val pageCount = event.pageCount()
    val pageRange = PageRange.of(1, pageCount)
    printJob.settings().pageRanges(pageRange).apply()
}

在通知浏览器开始打印之前,你还可以订阅 PrintCompleted 事件,以便在打印完成时收到通知:

Java
Kotlin
printJob.on(PrintCompleted.class, event -> {
    if (event.isSuccess()) {
        System.out.println("Printing is completed successfully.");
    } else {
        System.out.println("Printing has failed.");
    }
});
printJob.subscribe<PrintCompleted> { event ->
    if (event.isSuccess) {
        println("Printing is completed successfully.")
    } else {
        println("Printing has failed.")
    }
}

第 3 步:开始打印 

现在可以开始打印了:

Java
Kotlin
tell.proceed(printer);
tell.proceed(printer)

下面是完整代码片段:

Java
Kotlin
browser.set(PrintHtmlCallback.class, (params, tell) -> {
    var printer = params.printers()
            .defaultPrinter()
            .orElseThrow(IllegalStateException::new);
    var printJob = printer.printJob();
    printJob.settings()
            .header("<span style='font-size: 12px;'>Page header:</span>"
                    + "<span class='title'></span>")
            .footer("<span style='font-size: 12px;'>Page footer:</span>"
                    + "<span class='pageNumber'></span>")
            .paperSize(ISO_A4)
            .colorModel(COLOR)
            .enablePrintingBackgrounds()
            .disablePrintingHeaderFooter()
            .orientation(PORTRAIT)
            .apply();
    printJob.on(PrintCompleted.class, event -> {
        if (event.isSuccess()) {
            System.out.println("Printing is completed successfully.");
        } else {
            System.out.println("Printing has failed.");
        }
    });
    tell.proceed(printer);
});
browser.register(PrintHtmlCallback { params, tell ->
    val printer = params.printers.default!!
    val printJob = printer.job
    printJob.settings()
        .header("<span style='font-size: 12px;'>Page header:</span>"
                + "<span class='title'></span>")
        .footer("<span style='font-size: 12px;'>Page footer:</span>"
                + "<span class='pageNumber'></span>")
        .paperSize(ISO_A4)
        .colorModel(COLOR)
        .enablePrintingBackgrounds()
        .disablePrintingHeaderFooter()
        .orientation(PORTRAIT)
        .apply()
    printJob.subscribe<PrintCompleted> { event ->
        if (event.isSuccess) {
            println("Printing is completed successfully.")
        } else {
            println("Printing has failed.")
        }
    }
    tell.proceed(printer)
})

使用 PdfPrinter 打印的流程完全相同,不同之处在于你必须指定目标 PDF 文件路径:

Java
Kotlin
browser.set(PrintHtmlCallback.class, (params, tell) -> {
    var printer = params.printers().pdfPrinter();
    var printJob = printer.printJob();
    printJob.settings()
            .paperSize(ISO_A4)
            .enablePrintingBackgrounds()
            .pdfFilePath(Paths.get("<path-to-pdf-file>"))
            .apply();
    printJob.on(PrintCompleted.class, event -> {
        if (event.isSuccess()) {
            System.out.println("Printing is completed successfully.");
        } else {
            System.out.println("Printing has failed.");
        }
    });
    tell.proceed(printer);
});
browser.register(PrintHtmlCallback { params, tell ->
    val printer = params.printers.pdf
    val printJob = printer.job
    printJob.settings()
        .paperSize(ISO_A4)
        .enablePrintingBackgrounds()
        .pdfFilePath(Path("<path-to-pdf-file>"))
        .apply()
    printJob.subscribe<PrintCompleted> { event ->
        if (event.isSuccess) {
            println("Printing is completed successfully.")
        } else {
            println("Printing has failed.")
        }
    }
    tell.proceed(printer)
})

PrintPdfCallback 具有相同的接口,唯一的区别在于可应用到打印作业上的打印设置项不同。

取消打印 

要取消打印,请使用以下方式:

Java
Kotlin
browser.set(PrintCallback.class, (params, tell) -> tell.cancel());
browser.register(PrintCallback { params, tell ->
    tell.cancel()
})
微信咨询

即库客服

微信公众号二维码

技术客服

微信公众号二维码