2

我想直接从网页打印我的文件。为此,我使用以下参考并尝试使用 ZUL 和 Composer 实现相同的功能。

http://tonny-bruckers.blogspot.in/2012/11/printing-files-directly-from-web-page.html

ZUL 文件:-

<zk>
<applet code = "PrintApplet.class" codebase = "applet/" id="printApplet" width="400px" style="border: 1px" />
<button id="btnClickMe" label="Click Me" sclass="light-btn"/>
</zk>

PrintApplet.class 存在于“WebContent/applet”中。

public class AppletComposer extends GenericForwardComposer<Window> {
    private Applet printApplet;
    public void doOverrideAfterComposer(Window comp) throws Exception {

    }
    public void onClick$btnClickMe(Event event) throws Exception {
        String Originalstr = "ByteArrayInputStream Example!";
        byte[] Originalbytes = Originalstr.getBytes();
        ByteArrayInputStream bis=new ByteArrayInputStream(Originalbytes);
        printApplet.invoke("print", bis);
    }
}

PrintApplet 类:-

public class PrintApplet extends Applet {
    public void init() 
    {

    }
    public void print(ByteArrayInputStream bis) throws PrintException 
    {
        PrintService service = PrintServiceLookup.lookupDefaultPrintService();
        if (service != null) {
            DocFlavor psFormat = DocFlavor.INPUT_STREAM.PDF;
            PrintRequestAttributeSet attributes = new HashPrintRequestAttributeSet();    
            DocPrintJob job = service.createPrintJob();
            Doc pdfDoc = new SimpleDoc(bis,psFormat, null);
            job.print(pdfDoc, attributes);         
        }
    }
}

我可以使用这种方法调用 PrintApplet,但将 Null 作为服务。PrintApplet 与 AppletViewer 和普通 Java 应用程序一起工作正常,但在使用上述方法时无法获得默认打印机服务。

4

1 回答 1

2

首先我想提一下,小程序总是在客户端运行,小程序只与从它下载的服务器通信。

这就是为什么我们必须指定代码库目录,以便我们可以在客户端浏览器上下载小程序,然后浏览器的 JAVA 平台环境插件接管控制,然后在客户端 JRE 环境上运行。

所以我们必须非常小心地正确安装JDK环境。要跟踪小程序日志,我们可以使用 Java 小程序控制台工具“<strong>jconsole”。


APPLET 在客户端浏览器上正常运行的步骤:

  1. 在浏览器(firefox、chrome、opera)检查 JAVA 平台插件是否存在,因为要从浏览器运行小程序,我们需要安装并启用该插件。

    如果您在 linux 机器上工作:比它有点复杂,您可以从这里找到如何为 LINUX-BROWSER 启用插件:

    http://www.oracle.com/technetwork/java/javase/manual-plugin-install-linux-136395.html

  2. 为小程序启用控制台日志,当它在客户端 JRE 上执行时,我们可以查看它以进行跟踪。

    路径:JDK_DIR/bin/jcontrol

    [JControl 窗口][1]

    仅用于开发目的:您可以降低安全性

  3. 我们必须清除小程序的缓存,每次我们新建小程序时,为了反映最新的变化,我们需要先清除缓存,否则它会加载缓存的小程序类。

    要清除我们可以使用' javaws -viewer '

    路径:JAVA_HOME/bin/javaws -viewer

    [清除小程序缓存][2]


根据您的代码,您的服务器端代码(zul 和 composer)是完美的,但问题出在小程序代码上。

您正在 print() 方法中寻找默认打印机,这是一次性配置代码。它必须在 init() 中。

PrintApplet.java

public class PrintApplet extends Applet {

 private static final long serialVersionUID = 1L;
 private PrintService service;

 public void init() 
 {
    JOptionPane.showMessageDialog(null, "Inside INIT()");
    if(null==service){
        service = PrintServiceLookup.lookupDefaultPrintService();
        System.out.println(service.getName());
    } else {
        System.out.println(service.getName());
    }
 }
 public void print(String str) throws PrintException 
 {
    JOptionPane.showMessageDialog(null, "Inside print()");
    JOptionPane.showMessageDialog(null, "String is:::"+str);
    cPrint cP = new cPrint(str, service);
    System.out.println((Integer) AccessController.doPrivileged(cP));
 }
}

您需要 AccessController 的另一个实现来访问默认打印机定位和打印。

cPrint.java

class cPrint implements PrivilegedAction<Object> {
 String str;
 PrintService service;

 public cPrint(String str, PrintService argPrintService) {

    this.str = str;
    this.service = argPrintService;

 };
 public Object run() {
    // privileged code goes here
    InputStream is = null;
    try 
    {
        JOptionPane.showMessageDialog(null, "String is:::"+str);
        byte[] Originalbytes = str.getBytes();
        JOptionPane.showMessageDialog(null, "Original bytes:::"+Originalbytes);
        is=new ByteArrayInputStream(Originalbytes);
        FileWriter fstream = new FileWriter("/home/test/out.pdf");  
        BufferedWriter out = new BufferedWriter(fstream);  
        for (Byte b: Originalbytes) {  
            out.write(b);  
        }  
        out.close();
        DocPrintJob printJob = service.createPrintJob();
        Doc doc;
        DocAttributeSet docAttrSet = new HashDocAttributeSet();
        PrintRequestAttributeSet printReqAttr = new HashPrintRequestAttributeSet();
        doc = new SimpleDoc(is, DocFlavor.INPUT_STREAM.AUTOSENSE, docAttrSet);
        PrintJobWatcher pjDone = new PrintJobWatcher(printJob);
        printJob.print(doc, printReqAttr);
        pjDone.waitForDone();
        // It is now safe to close the input stream
        is.close();
     } 
     catch (Exception e) {
        e.printStackTrace();
        System.out.println(e);
        return 1;
     } 
    return 0;
  }
  static class PrintJobWatcher {
    // true iff it is safe to close the print job's input stream
    boolean done = false;

    PrintJobWatcher(DocPrintJob job) {
        // Add a listener to the print job
        job.addPrintJobListener(new PrintJobAdapter() {
            public void printJobCanceled(PrintJobEvent pje) {
                allDone();
            }
            public void printJobCompleted(PrintJobEvent pje) {
                allDone();
            }
            public void printJobFailed(PrintJobEvent pje) {
                allDone();
            }
            public void printJobNoMoreEvents(PrintJobEvent pje) {
                allDone();
            }
            void allDone() {
                synchronized (PrintJobWatcher.this) {
                    done = true;
                    PrintJobWatcher.this.notify();
                }
            }
        });
    }
    public synchronized void waitForDone() {
        try {
            while (!done) {
                wait();
            }
        } catch (InterruptedException e) {
        }
    }
 }
}

cPrint(str,PrintService)

如果要打印文件,str 可以是文件名,也可以是字节数组字符串。

在我的示例中,我期望字节数组,因此我从作曲家的小程序给出的字节数组创建 pdf 文件,然后将其发送到给定的默认打印机PrintService

因此,zk 中的小程序获取默认打印机的访问权限并进行打印的实际流程是通过此 [graph][3] 进行的。

于 2015-12-30T18:01:41.347 回答