web应用票据打印实现(四)

news/2024/11/29 23:50:27/

上一篇中,我们已经通过iText生成了共打印的pdf文档,如果没有特别的要求,利用浏览器的pdf插件来预览和打印已经能供满足我们Web应用在浏览器端实现票据套打的要求了。但在我们的项目中,客户要求一次操作之后连续进行打印,即使用不同的数据填充模板,连续套打上百张的票据。
当时考虑的实现方式有两种:

  • 生成一个多页的pdf文档,还是利用浏览器的pdf插件来进行打印
  • 生成多个pdf文档,使用applet利用java print service来进行浏览器端的连续打印

最终我们选择了第二种方案,好处是浏览器不用打开新的tab来显示pdf文档,用户的注意力可以始终停留在同一页面。此外打印选项可以直接显示在页面中,比较直观。

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.print.*;import java.io.IOException;
import java.io.InputStream;import java.nio.ByteBuffer;import javax.print.PrintService;
import javax.print.PrintServiceLookup;import com.sun.pdfview.PDFFile;
import com.sun.pdfview.PDFPage;
import com.sun.pdfview.PDFPrintPage;public class PDFPrintApplet extends JApplet implements ActionListener {/*** */private static final long serialVersionUID = 6293078385198700265L;private PrintService[] services;private boolean degugFlg = true;private PrinterJob pjob = PrinterJob.getPrinterJob();private JComboBox printerList;private JButton printBtn;public void init() {// 创建applet的GUI,由event dispatching thread运行try {SwingUtilities.invokeAndWait(new Runnable() {public void run() {createGUI();}});} catch (Exception e) {System.err.println("createGUI didn't complete successfully");}}//简单的打印选项UI,只包括选择打印机,可以根据需要添加更多的选项private void createGUI() {JLabel lbl = new JLabel("选择打印机: ");String[] printerServiceNames = getAllAvailablePrintServicesNames();printerList = new JComboBox(printerServiceNames);printerList.addActionListener(this);JPanel printerSelectorPanel = new JPanel(new FlowLayout());printerSelectorPanel.setBackground(Color.WHITE);printerSelectorPanel.add(lbl);printerSelectorPanel.add(printerList);JPanel buttonPanel = new JPanel();buttonPanel.setBackground(Color.WHITE);printBtn = new JButton("打印");printBtn.addActionListener(this);buttonPanel.add(printBtn);setLayout(new GridLayout(2, 1));add(printerSelectorPanel);add(buttonPanel);}public void actionPerformed(ActionEvent e) {if (e.getSource() == printBtn) {launchPrint();} else if (e.getSource() == printerList) {JComboBox cb = (JComboBox) e.getSource();String printerName = (String) cb.getSelectedItem();setSelectedPrintService(printerName);}}//得到要打印的pdf文件的url列表,并开始打印private void launchPrint() {final List<String> inputArr = convertArrayParameter(getParameter("pdfFileNameArray"));try {List<URL> pdfInputStreamList = load(inputArr);          print(pdfInputStreamList);} catch (MalformedURLException e) {e.printStackTrace();} catch (URISyntaxException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}// 根据传给Applet的参数,下载相应的PDF文件,生成URLprivate List<URL> load(List<String> fileNameList)throws URISyntaxException, IOException {List<URL> pdfURLList = new ArrayList<URL>();for (String fileName : fileNameList) {URL url = new URL(fileName);pdfURLList.add(url);}return pdfURLList;}// 解析传给Applet的参数,将以逗号分隔的字符串分成参数Listprivate List<String> convertArrayParameter(String parameterArrStr) {List<String> list = new ArrayList<String>();String[] parameterArr = parameterArrStr.split(",");Collections.addAll(list, parameterArr);return list;}// 将InputStream转为ByteBufferprivate ByteBuffer getByteBufferFormInputStream(InputStream is)throws IOException {int BUFSIZE = 1024;List<Byte> byteV = new ArrayList<Byte>();byte[] tmp1 = new byte[BUFSIZE];while (true) {int r = is.read(tmp1, 0, BUFSIZE);if (r == -1)break;for (int i = 0; i < r; i++) {byteV.add(new Byte(tmp1[i]));}}byte[] tmp2 = new byte[byteV.size()];for (int i = 0; i < byteV.size(); i++) {tmp2[i] = byteV.get(i).byteValue();}return ByteBuffer.wrap(tmp2);}// 得到本地所有可用的打印服务名private String[] getAllAvailablePrintServicesNames() {services = PrintServiceLookup.lookupPrintServices(null, null);if (services.length == 0) {}String[] printServicesNames = new String[services.length];for (int i = 0; i < services.length; i++) {printServicesNames[i] = services[i].getName();}return printServicesNames;}// 设置要使用的打印服务private void setSelectedPrintService(String serviceName) {try {for (PrintService service : services) {if (service.getName().equals(serviceName)) {pjob.setPrintService(service);return;}}} catch (PrinterException e) {// TODO Auto-generated catch blocke.printStackTrace();}}private void setDefaultPrintService() {services = PrintServiceLookup.lookupPrintServices(null, null);while (services.length == 0) {services = PrintServiceLookup.lookupPrintServices(null, null);}int j = 0;for (PrintService ps : services) {if (ps.getName().equals("doPDF v7")) {try {pjob.setPrintService(services[j]);} catch (PrinterException e) {// TODO Auto-generated catch blocke.printStackTrace();}} else {j++;}}}//执行打印private void print(List<URL> pdfURLList) throws IOException {if (pjob.getPrintService() == null && degugFlg == true) {setDefaultPrintService();}for (URL pdfURL : pdfURLList) {ByteBuffer buf = getByteBufferFormInputStream(pdfURL.openStream());PDFFile pdfFile = new PDFFile(buf);PDFPrintPage pages = new PDFPrintPage(pdfFile);PDFPage page = pdfFile.getPage(1);PageFormat pf = pjob.defaultPage();pf.setOrientation(PageFormat.PORTRAIT);Paper paper = new Paper();paper.setSize(page.getWidth(), page.getHeight());// This is to fix an error in PDF-Renderer// View// http://juixe.com/techknow/index.php/2008/01/17/print-a-pdf-document-in-java/// for details// Printing a PDF is also possible by sending the bytes directly to// the printer, but// the printer would have to support it.paper.setImageableArea(0, 0, paper.getWidth() * 2,paper.getHeight());Book book = new Book();pf.setPaper(paper);book.append(pages, pf, 1);pjob.setPageable(book);try {pjob.print();} catch (PrinterException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}
}

上面是applet代码,通过Java Network Launch Protocol (JNLP) 协议来部署applet,并传入数据,JS代码如下:

var attributes = {code:'PDFPrintApplet',width:500, height:200} ;
var jnlp_path= '<%=basePath%>applet/pdfprintapplet.jnlp';
var parameters = {jnlp_href : jnlp_path,//这个参数就是传递给applet的待打印pdf文件的url列表pdfFileNameArray : array
};
var version = '1.6';
deployJava.runApplet(attributes, parameters, version);

http://www.ppmy.cn/news/382124.html

相关文章

web应用票据打印实现(一)

许多web应用的开发中都会涉及到票据打印的功能。常用的Web打印实现的方式有&#xff1a; 1.浏览器打印接口 调用window.print()方法&#xff0c;调用打印机功能打印当前窗口的内容&#xff0c;与单击浏览器的打印按钮效果一致。示例代码如下&#xff1a; <html> …

怎么在一张A4纸上打印2张发票?

平时我们在打印发票时&#xff0c;直接打开会被放大到铺满整张A4纸&#xff0c;这样就会失真&#xff0c;那么应该怎么设置才能让一张A4纸上打印2张发票呢&#xff1f; 1、Word格式 方式1&#xff1a;首先新建一个Word文档后&#xff0c;插入2张发票&#xff0c;并适当排版在…

票据打印, 银行账单打印, 标签印刷, 文档打印, 条码打印, 批量打印, 包装纸打印与设计,可变数据打印,数据库印刷,HMI报表打印,VC++源码库解决方案

票据打印, 银行账单打印, 标签印刷, 文档打印, 条码打印, 批量打印, 包装纸打印与设计&#xff0c;可变数据打印&#xff0c;数据库印刷&#xff0c;HMI报表打印&#xff0c;VC源码库解决方案 -- 全球领先、100%源码全开放、可用于HMI组态报表打印的解决方案&#xff01;   使…

精锐万能票据打印专家

精锐万能票据打印专家是由昆明灵豚科技有限公司面向票据处理市场推出专业票据打印软件。利用该软件可轻松打印现金支票、转帐支票、旅行支票、转账支票、贷记凭证、电汇凭证、信汇凭证、进账单、现金结款单、快递单、汇/本票申请书、收据、各种证件等格式 精锐万能票据打印专家…

Java调用热敏票据打印机打印小票

package com.yc.printer; /** * 源辰信息 * 商品信息 * author navy * 2017年5月23日 */ public class GoodsInfo { private String gname; //商品名称 private String price; //商品单价 private String num; //商品数量 private String total; //小计 Override public Strin…

简单打印-80pos小票模板

设计模板参考 简单打印-双排标签102*30模板设计 简单打印-快递单套打 知识点: 排版横线技巧排版横线上方覆盖居中标签公式应用 自动计算价格 更多功能 请自行挖掘 数据&#xff1a; {"setting": [{"action": "preview","template"…

热敏打印机ESCPOS指令封装类,票据打印从此轻松,佳博系列实测通过

开发背景 接到一个任务&#xff0c;要用热敏打印机打印小票。本人用的是市面上比较常见的佳博热敏打印机。用过票据打印机的人都知道&#xff0c;在小票上打印与普通的打印纸上打印不一样。要通过发送ESCPOS 指令给打印机来完成打印任务&#xff0c;所以控制热敏打印可以看作是…

java:打印发票

java第一次作业 可以继续改进&#xff0c;仅供参考(。・&#xff3f;・。)&#xff1a; 1.在一个文件中创建一个商品类&#xff1a; package carlos.way; /** * 商品 * author Mr.zhang * */ public class Shipping { String no; String name; int count; …