远程驱动打印PDF
最近接到一个需求:包装员扫描完SKU后,需要打印PDF面单,为了提高业务效率,包装员不必手动下载PDF后再手动操作打印,要实现自动驱动打印机来打印PDF。
思路:pdf面单存在服务器上,打印机是连接包装员的电脑的。在每个包装员电脑上安装一个打印接口服务(远程获取PDF保存到本地,然后直接驱动打印机打印,打印完删除本地文件),当业务流程走到需要打印PDF的时候,调用对应的接口(每个包装员的电脑安装一个打印接口)打印PDF面单。
首先确定怎么打印PDF:
引用Apache的pdfbox-tools开源项目,驱动打印机打印本地PDF文件(不支持打印远程pdf文件)。
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox-tools</artifactId>
<version>2.0.11</version>
</dependency>
打印PDF只须调用PrintPDF类的main方法即可^_^
public static void main(String[] args) {//test
String printerName = "PDFCreator";//打印机名
String pdfFilePath = "D:/pdf/39488.pdf";//pdf路径
try {
PrintPDF.main(new String[] {
"-silentPrint",// 静默打印
// "-password","abcde",//pdf打开密码
"-printerName", printerName,// 指定打印机名
"-orientation", "auto",// 打印方向,auto|landscape|portrait三种可选
pdfFilePath // 打印PDF文档的路径
});
} catch (Exception e) {
e.printStackTrace();
}
}
然后写个打印接口服务,一个简单的Spring-Boot接口项目从远程(erp服务拿到pdf文件,直接驱动打印机打印)下载pdf到打印接口本地,然后直接打印,打印完成,删除本地文件。然后打成jar包,得到pdfPrintSoa-0.0.1-SNAPSHOT.jar
//打印接口服务
@RestController
@EnableAutoConfiguration
@RequestMapping("/")
public class PdfController {
//从远程(erp服务拿到pdf文件,直接驱动打印机打印)下载pdf到打印接口本地,然后直接打印,打印完成,删除本地文件
@RequestMapping("printPdfByUrl")
@ResponseBody
public boolean printPdfByUrl(@RequestBody PdfParam pdf) {
String orderNo = null;
try {
String printerName = pdf.getPrinterName();//打印机名
String url = pdf.getUrl();//pdf远程url
orderNo = pdf.getOrderNo();
System.out.println("printerName:" + printerName + ", orderNo:" + orderNo);
if(null == printerName || url == null || orderNo == null) {
System.out.println("参数不能为空");
return false;
}
//pdf下载到本地临时存放
String pdfFilePath = "C:/pdf/" + orderNo + ".pdf";
downloadNet(url,pdfFilePath);// 下载网络文件
if(!new File(pdfFilePath).exists()){
System.out.println(pdfFilePath + " not exist!");
return false;
}
PrintPDF.main(new String[]{
"-silentPrint",//静默打印
// "-password","abcde",//pdf打开密码
"-printerName",printerName ,//指定打印机名
"-orientation","auto",//打印方向,auto|landscape|portrait三种可选
pdfFilePath//打印PDF文档的路径
});
deleteFile(pdfFilePath);//删除打印完的文件
System.out.println("orderNo:" + orderNo + "pdf面单打印成功!");
return true;
}catch(Exception e){
e.printStackTrace();
System.out.println("orderNo:" + orderNo + "pdf面单打印失败!");
}
return false;
}
// 下载网络文件
private static void downloadNet(String sourceFileUrl,String destFilePath){
int bytesum = 0;
int byteread = 0;
InputStream inStream = null;
FileOutputStream fs = null;
try {
URL url = new URL(sourceFileUrl);
URLConnection conn = url.openConnection();
inStream = conn.getInputStream();
fs = new FileOutputStream(destFilePath);
byte[] buffer = new byte[1024*4];
while ((byteread = inStream.read(buffer)) != -1) {
bytesum += byteread;
System.out.println(bytesum);
fs.write(buffer, 0, byteread);
}
} catch (Exception e) {
e.printStackTrace();
} finally{
try {
if(inStream != null){
inStream.close();
}
if(fs != null){
fs.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
private static void deleteFile(String filePath) {
File file = new File(filePath);
if (file.exists() && file.isFile()) {
file.delete();
}
}
public static void main(String[] args) {//test
String printerName = "PDFCreator";//打印机名
//pdf路径
String pdfFilePath = "D:/pdf/39488.pdf";
try {
PrintPDF.main(new String[]{
"-silentPrint",//静默打印
// "-password","abcde",//pdf打开密码
"-printerName",printerName ,//指定打印机名
"-orientation","auto",//打印方向,auto|landscape|portrait三种可选
pdfFilePath//打印PDF文档的路径
});
} catch (PrinterException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
nginx配置,通过alias设置虚拟目录,这样就可以通过URL直接远程访问PDF了(打印接口服务就是这样远程下载PDF的)。
location /static {
alias /home/pdf/;
}
比如nginx配置的域名是www.liu.com,访问http://www.liu.com/static/39488.pdf实际指向的是/home/pdf/394488.pdf
最后,写个DOS批处理文件(pdf打印机启动.bat)给包装员用来启动打印接口服务。
PS:先把打印接口项目生成的jar包pdfPrintSoa-0.0.1-SNAPSHOT.jar放进pdf夹子里,pdf夹子放到c盘
@echo off
cd c:\pdf
java -jar pdfPrintSoa-0.0.1-SNAPSHOT.jar
打印接口服务启动后,需要打印PDF时,通过Http调用包装员电脑对应的打印接口服务就可以了,实现远程驱动打印PDF面单。