Java打印带有选项(装订,双面打印等)的PDF [英] Java printing PDF with options (staple, duplex, etc)

查看:284
本文介绍了Java打印带有选项(装订,双面打印等)的PDF的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个可打印PDF的Java程序.它使用Apache PDFBox创建 PDDocument 对象(在某些情况下是从pdf文档或从流中),然后使用 javax.print API将其发送到打印机:

I have a java program that prints PDFs. It uses Apache PDFBox to create a PDDocument object (from a pdf document or from a stream in some cases) and then sends it to the printer using the javax.print API:

private boolean print(File pdf, String printer)
{
    boolean success = false;

    try (PDDocument document = PDDocument.load(pdf))
    {
        PrintService[] printServices = PrinterJob.lookupPrintServices();
        PrintService printService = PrintServiceLookup.lookupDefaultPrintService();
        PrinterJob job = PrinterJob.getPrinterJob();
        job.setPageable(new PDFPageable(document));

        // set printer
        if (printer != null)
        {
            for (PrintService selected : printServices)
            {
                if (selected.getName().equals(printer))
                {
                    printService = selected;
                    break;
                }
            }
        }
        job.setPrintService(printService);
        job.print();
        success = true;
    }
    catch (Exception e)
    {
        myLog.error("Printer error.", e);
    }
    return success;
}

现在,我需要能够告诉打印机将东西装订起来...

Now I need to be able to tell the printer to staple the thing...

我熟悉javax.print.attributes API,并成功地将其用于指定纸盘或设置双面打印,例如:

I am familiar with the javax.print.attributes API and use this successfully for specifying the tray or setting duplex, e.g.:

// this works fine
if (duplex != null)
{               
    if (duplex.equalsIgnoreCase("short"))
    {
        myLog.debug("Setting double-sided: Short");
        attr.add(Sides.TWO_SIDED_SHORT_EDGE);
    }
    else
    {
        myLog.debug("Setting double-sided: Long");
        attr.add(Sides.TWO_SIDED_LONG_EDGE);
    }
}

我知道有一个用于装订的属性:

I know there is an attribute for stapling:

attr.add(javax.print.attribute.standard.Finishings.STAPLE);

我有一个带有Finisher XL附件的Xerox Versalink B7035,该附件完全支持装订(即,它在MS Office文档设置中有效),但是打印机不理会Java设置的STAPLE属性.我尝试了装订属性的所有其他变体,但很快发现打印机不支持任何Java精加工属性.

I have a Xerox Versalink B7035 with a Finisher XL attachment that fully supports stapling (i.e. it works from MS Office document settings) however the printer disregards the STAPLE attribute set from Java. I tried all other variants of staple attributes but soon found that the printer did not support ANY Java finishing attributes.

或者将其放入代码中,以下内容不会显示任何结果:

Or to put it in code, the following prints NO results:

DocFlavor flavor = DocFlavor.SERVICE_FORMATTED.PRINTABLE;
Object finishings = myPrinter.getSupportedAttributeValues(Finishings.class, flavor, null);
if (finishings != null && o.getClass().isArray())
{
    for (Finishings finishing : (Finishings[]) finishings)
    {
        System.out.println(finishing.getValue() + " : " + finishing);
    }
}

在阅读并尝试一些其他操作后,我得出结论打印机将不接受STAPLE属性,因为装订器是附件或仅仅是因为Xerox不喜欢Java或其他东西.因此,现在我尝试通过在发送如此处所述之前在pdf之前添加PJL命令来解决此问题.* PJL =打印作业语言

After reading this and trying a few different things I concluded the printer will not accept the STAPLE attribute because the finisher is an attachment or simply because Xerox doesn't like Java or something. So now I am attempting to solve this by prepending PJL commands to the pdf before sending it, as covered here. *PJL = Print Job Language

例如:

<ESC>%-12345X@PJL<CR><LF>
@PJL SET STAPLE=LEFTTOP<CR><LF>
@PJL ENTER LANGUAGE = PDF<CR><LF>
[... all bytes of the PDF file, starting with '%PDF-1.' ...]
[... all bytes of the PDF file ............................]
[... all bytes of the PDF file ............................]
[... all bytes of the PDF file, ending with '%%EOF' .......]
<ESC>%-12345X

起初,我假设 Apache PDFBox库中将有某种方法可以执行只是这个,但是没有运气.然后,我签出了 Ghost4J 的API,却没有看到任何可以作为前缀的内容.有人解决了吗?

At first I assumed there would just be some method in the Apache PDFBox library to do just this, but no luck. Then I checked out the API for Ghost4J and saw nothing for prepending. Has anyone else solved this already?

推荐答案

恢复到Java套接字打印使PJL成为一件事情:

Reverting to Java socket printing makes PJL a thing:

// this works, it also printed faster than javax.print when tested
private static void print(File document, String printerIpAddress, boolean staple)
{
    try (Socket socket = new Socket(printerIpAddress, 9100))
    {
        DataOutputStream out = new DataOutputStream(socket.getOutputStream());
        byte[] bytes = Files.readAllBytes(document.toPath());

        out.write(27); //esc
        out.write("%-12345X@PJL\n".getBytes());
        out.write("@PJL SET DUPLEX=ON\n".getBytes());

        if (staple) 
        {
            out.write("@PJL SET STAPLEOPTION=ONE\n".getBytes());
        }
        out.write("@PJL ENTER LANGUAGE=PDF\n".getBytes());
        out.write(bytes);
        out.write(27); //esc
        out.write("%-12345X".getBytes());
        out.flush();
        out.close();
    }
    catch (Exception e)
    {
        System.out.println(e);
    }
}

所需的PJL命令来自此施乐数据表.

The needed PJL commands came from this Xerox datasheet.

应该注意的是,相同的PJL命令适用于两种不同的Xerox型号 Lexmark打印机,这些都是我方便测试的.邓诺,如果其他模特想要其他东西.

It should be noted that the same PJL commands worked for two different Xerox models and a Lexmark printer, that's all I had handy to test with. Dunno if other models will want something different.

不再需要Apache PDFBox库.或任何外部库.

Do not need the Apache PDFBox library anymore. Or any external libraries at all.

这可能适用于除PDF之外的其他类型的文档.

This might work for other types of documents, aside from PDFs.

这篇关于Java打印带有选项(装订,双面打印等)的PDF的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆