Печать на конкретный принтер (IPP URI) в Java

Есть ли какой-либо способ в Java для печати на определенный IPP-принтер? Все примеры кода и учебников, которые я нашел, сосредоточены на том, как печатать определенный тип документа, используя что-то вроде следующего:

DocFlavor flavor = DocFlavor.INPUT_STREAM.POSTSCRIPT;
PrintRequestAttributeSet aset = new HashPrintRequestAttributeSet();
aset.add(MediaSizeName.ISO_A4);
PrintService[] pservices =
             PrintServiceLookup.lookupPrintServices(flavor, aset);
if (pservices.length > 0) {
    DocPrintJob pj = pservices[0].createPrintJob();
    try {
        FileInputStream fis = new FileInputStream("test.ps");
        Doc doc = new SimpleDoc(fis, flavor, null);
        pj.print(doc, aset);
    } catch (FileNotFoundException fe) {
    } catch (PrintException e) { 
    }
}

Этот фрагмент просто печатает на первом найденном принтере, который способен печатать документ. В моем случае я хочу искать принтер по его URI, но PrintServiceLookup, похоже, не поддерживает это. Я попытался использовать PrintServiceAttributeSet вместо PrintRequestAttributeSet и добавить атрибут PrinterURI, но не возвращает никаких принтеров. Я подозреваю, что служба поиска ищет принтер, который может изменить URL-адрес получателя, вместо того, чтобы искать принтер с этим URI.

В крайнем случае я подумал о просто перечислении всего PrintService, возвращаемого lookupPrintServices, но URI не принадлежит ни одному из атрибутов. Имя принтера есть, но мне нужен URI.

Для фона мой webapp должен печатать штрих-код на конкретном принтере на основе текущего пользователя. Каждый пользователь связан с URI принтера, который указывает на принтер на сервере CUPS. URI принтера - единственная информация, которую я имею, и я не могу ограничить имя принтера в соответствии с URI или подстрокой URI.

Изменить: Чтобы немного уточнить, мне не нужно отображать данные, мне просто нужно скопировать blob на данный принтер. Часть, которую я не могу понять, заключается в том, как идентифицировать принтер по его IPP URI.

Ответы

Ответ 1

Наконец-то я нашел способ сделать это, используя jipsi:

URI printerURI = new URI("ipp://SERVER:631/printers/PRINTER_NAME");
IppPrintService svc = new IppPrintService(printerURI);
InputStream stream = new BufferedInputStream(new FileInputStream("image.epl"));
DocFlavor flavor = DocFlavor.INPUT_STREAM.AUTOSENSE;
Doc myDoc = new SimpleDoc(stream, flavor, null);
DocPrintJob job = svc.createPrintJob();
job.print(myDoc, null);

Я должен признать, что я разочарован тем, что должен использовать стороннюю библиотеку, чтобы сделать что-то такое, казалось бы, простое, как печать на конкретном принтере.

UPDATE

DR указывает в комментариях, что jipsi имеет новый home, и новое имя.

Cups4J - хорошая альтернатива, но, как видно из названия, она может работать неправильно, если пункт назначения не является сервером CUPS. У меня были хорошие результаты, используя Cups4J для печати непосредственно на термопринтер Zebra.

Ответ 2

Я не думаю, что вы можете получить принтер так, как вам хотелось бы (я думаю, что механизм печати Java предшествует IPP).

Однако, если я правильно помню, я смогу выполнить локальное задание печати и затем отправить байты выходного потока на целевой сервер CUPS "вручную". Будет ли это "достаточно хорошим" для вас?