16

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属性,但这不会返回任何打印机。我怀疑查找服务正在寻找可以更改其目标 URI 的打印机,而不是寻找具有该 URI 的打印机。

作为最后的手段,我考虑只枚举由PrintServices 返回的所有 s lookupPrintServices,但 URI 不在任何属性中。打印机名称在那里,但我需要 URI。

对于背景,我的 webapp 需要根据当前用户将条形码打印到特定的打印机。每个用户都与一个打印机 URI 相关联,该 URI 指向 CUPS 服务器上的打印机。打印机 URI 是我拥有的唯一信息,我无法限制打印机名称以匹配 URI 或 URI 的子字符串。

编辑:澄清一下,我不需要渲染数据,我只需要将 blob 复制到给定的打印机。我无法弄清楚的部分是如何通过其 IPP URI 识别打印机。

4

3 回答 3

17

我终于找到了一种方法来做到这一点,通过使用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);

我不得不承认,我对不得不使用 3rd-party 库来做一些看似简单的事情(比如打印到特定打印机)感到很失望。

更新

DR 在评论中指出 jipsi 有一个新家和一个新名称。

Cups4J是一个不错的选择,但顾名思义,如果目标不是 CUPS 服务器,它可能无法正常工作。使用 Cups4J 直接打印到 Zebra 热敏打印机时,我取得了很好的效果。

于 2009-11-02T18:24:41.863 回答
1

我不认为您可以按照自己想要的方式获得打印机(我认为 Java 打印机制早于 IPP)。

但是,如果我没记错的话,您可以在本地渲染您的打印作业,然后“手动”将输出流的字节发送到目标 CUPS 服务器。这对你来说“足够好”了吗?

于 2009-10-31T19:24:57.277 回答
1

要仅通过 IPP 将 PDF 等可打印文档格式提交到打印机(或 CUPS),此代码提供了一个没有依赖关系的简约实现。ipp-printjob-java对解码 ipp 响应有基本的支持。

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URI;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;

public class IppPrintJob {

  public static void main(String args[]) throws Exception {
    URI printerURI = URI.create("http://colorjet:631/ipp/printer");
    File file = new File("A4-blank.pdf");
    short status = new IppPrintJob()
      .printDocument(printerURI, new FileInputStream(file));
    System.out.println(String.format("ipp status: %04X", status));
  }

  short printDocument(
    URI uri, InputStream documentInputStream
  ) throws IOException {
    HttpURLConnection httpURLConnection =
      (HttpURLConnection) uri.toURL().openConnection();
    httpURLConnection.setDoOutput(true);
    httpURLConnection.setRequestProperty("Content-Type", "application/ipp");
    OutputStream outputStream = httpURLConnection.getOutputStream();
    DataOutputStream dataOutputStream =
      new DataOutputStream(httpURLConnection.getOutputStream());
    dataOutputStream.writeShort(0x0101); // ipp version
    dataOutputStream.writeShort(0x0002); // print job operation
    dataOutputStream.writeInt(0x002A); // request id
    dataOutputStream.writeByte(0x01); // operation group tag
    writeAttribute(dataOutputStream, 0x47, "attributes-charset", "utf-8");
    writeAttribute(dataOutputStream, 0x48, "attributes-natural-language", "en");
    writeAttribute(dataOutputStream, 0x45, "printer-uri", uri.toString());
    dataOutputStream.writeByte(0x03); // end tag
    documentInputStream.transferTo(outputStream);
    dataOutputStream.close();
    outputStream.close();
    if (httpURLConnection.getResponseCode() == 200) {
      DataInputStream dataInputStream =
        new DataInputStream(httpURLConnection.getInputStream());
      System.out.println(String.format("ipp version %d.%s",
        dataInputStream.readByte(), dataInputStream.readByte()
      ));
      return dataInputStream.readShort();
    } else {
      throw new IOException(String.format("post to %s failed with http status %d",
        uri, httpURLConnection.getResponseCode()
      ));
    }
  }

  void writeAttribute(
    DataOutputStream dataOutputStream, int tag, String name, String value
  ) throws IOException
  {
    Charset charset = StandardCharsets.UTF_8;
    dataOutputStream.writeByte(tag);
    dataOutputStream.writeShort(name.length());
    dataOutputStream.write(name.getBytes(charset));
    dataOutputStream.writeShort(value.length());
    dataOutputStream.write(value.getBytes(charset));
  }

}
于 2020-03-19T14:20:16.930 回答