使用小程序时无法获取默认打印机名称 - ZK Framework

Unable to get default printer name while using applet - ZK Framework

我想直接从网页打印我的文件。为此,我正在使用以下参考资料并尝试使用 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);
    }
}

打印小程序 Class :-

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 应用程序中工作正常,但在使用上述方法时无法获得默认打印机服务。

First I want to mention that APPLET IS ALWAYS RUN ON CLIENT SIDE and APPLET only communicates to the server which from it is downloaded.

That’s why we have to specify codebase directory, so that we can download the applet on client browser by then JAVA Platform Environment plugin from browser takes on control, which in turn run on client JRE environment.

So we have to be very carefully that JDK environment is installed properly. To trace applet log we can use of java applet console tool ‘jconsole’.


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

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

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

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

  2. 启用applet的console log,当它在客户端JRE上执行时,我们可以查看它进行跟踪。

    路径:JDK_DIR/bin/jcontrol

    [JControl Window][1]

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

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

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

    路径:JAVA_HOME/bin/javaws-查看器

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


As per your code, your server side code (zul and composer) are perfect but the problem is at applet code.

You are looking for a default printer in print() method, which are one time configuration codes. It has to be in 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));
 }
}

And you need another implementation of AccessController to give access to the default printer locate and print.

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)

Where str can be file name if you want file to be print, or byte array string.

Here in my example, I expected byte array, so I create pdf file from byte array given by the applet from the composer and then it'll sent to the default printer to the given PrintService.

So Actual flow for applet in zk to get access for default printer and to print is by this [graph][3].