Java печать PDF с опциями (сшивание, дуплекс и т. Д.) - PullRequest
0 голосов
/ 21 апреля 2019

У меня есть Java-программа, которая печатает PDF-файлы. Он использует Apache PDFBox для создания PDDocument объекта (из документа PDF или в некоторых случаях из потока), а затем отправляет его на принтер с помощью 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;
}

Теперь мне нужно указать принтеру, чтобы он скреплял вещи ...


Я знаком с API-интерфейсом javax.print.attributes и успешно использую его для указания лотка или настройки дуплекса, например ::

.
// 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);
    }
}

Я знаю, что есть атрибут для сшивания:

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

У меня есть Xerox Versalink B7035 с вложением Finisher XL, которое полностью поддерживает сшивание (т. Е. Оно работает из настроек документа MS Office), однако принтер игнорирует набор атрибутов STAPLE из Java. Я перепробовал все другие варианты атрибутов сшивания, но вскоре обнаружил, что принтер не поддерживает ЛЮБЫЕ атрибуты завершения Java.

Или, если поместить его в код, выведите следующие НЕТ результатов:

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 или что-то еще. Итак, теперь я пытаюсь решить эту проблему, добавляя команды PJL в pdf перед отправкой, , как описано здесь . * PJL = язык задания на печать

например:

<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 просто будет какой-то метод, но не удача. Затем я проверил API для Ghost4J и ничего не предвидел. Кто-нибудь еще решил это уже?

1 Ответ

0 голосов
/ 21 апреля 2019

Возврат к печати через сокет Java делает PJL непонятным:

// 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 получены из этой таблицы данных Xerox .

Следует отметить, что одни и те же команды PJL работали для двух разных моделей Xerox и принтера Lexmark, и это все, с чем мне было удобно тестировать.Не знаю, если другие модели захотят что-то другое.

Больше не нужна библиотека Apache PDFBox.Или вообще любые внешние библиотеки.

Это может работать для других типов документов, кроме PDF.

...