通过后台Servlet打印jsp页面

通过后台打印jsp画面的Servlet,通过后台访问jsp画面得到相应的画面html,然后转化为pdf,输出到打印机

<p>通过ajax post,url为http://localhost/printJsp.do?jspName=FMBDRPDEMO1.jsp<p/>

web.xml:

<servlet>
        <servlet-name>printJsp</servlet-name>
        <servlet-class>com.baosight.wms.common.beans.ServletPrintJsp</servlet-class>

    </servlet>

<servlet-mapping>
        <servlet-name>printJsp</servlet-name>
        <url-pattern>/printJsp.do</url-pattern>
    </servlet-mapping>

public class ServletPrintJsp extends HttpServlet{



private static final long serialVersionUID = 1L;
private static final Logger log = LoggerFactory.getLogger(ServletPrintJsp.class);


@Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }

@Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
        response.setHeader("content-type", "text/html;charset=UTF-8");
        response.setCharacterEncoding("UTF-8");
        
        //获取参数
        String printReportId = request.getParameter(BM2PReportConstants.PARA_PRINT_REPORT_ID);//打印报表ID
        String keyword = request.getParameter(BM2PReportConstants.PARA_KEYWORD);//关键字
        String formEname = request.getParameter(BM2PReportConstants.PARA_FORM_ENAME);//调用画面英文名
        String buttonEname = request.getParameter(BM2PReportConstants.PARA_BUTTON_ENAME);//调用按钮英文名
        
        //根据打印报表ID查询对应的报表画面和打印机
        Tfmbdc0 printReportConfig = FMManagerFactory.getMgrPrintReportConfig().getPrintReportConfigByUI(printReportId);
        String reportFormEname = printReportConfig.getReportFormEname();
        String printerName = printReportConfig.getPrinterName();
        
        //通过后台访问的url地址
        String url = MessageFormat.format("/DispatchAction.do?efFormEname={0}&printReportId={1}&keyword={2}&previewFlag=0", reportFormEname, printReportId, keyword);
        
        final ByteArrayOutputStream os =new ByteArrayOutputStream();
        final ServletOutputStream stream =new ServletOutputStream() {
            public boolean isReady() {
                return false;
            }
            public void setWriteListener(WriteListener writeListener) {
            }
            public void write(byte[] data, int offset, int length){
                os.write(data, offset, length);
            }
            @Override
            public void write(int b) throws IOException {
                os.write(b);
            }
        };


        final PrintWriter pw =new PrintWriter(new OutputStreamWriter(os,  "utf-8"));//保存html中文乱码
        HttpServletResponse rep =new HttpServletResponseWrapper(response){
            public ServletOutputStream getOutputStream(){
                return stream;
            }
            public PrintWriter getWriter(){
                return pw;
            }
        };
        rep.setHeader("content-type", "text/html;charset=UTF-8");
        rep.setCharacterEncoding("UTF-8");
        
        ServletContext sc = getServletContext();
        RequestDispatcher rd = sc.getRequestDispatcher(url);
        //include 最后的主导权仍保留在本servlet
        rd.include(request, rep);
        
        //获取当前服务器部署目录的物理路径
        String currentPath = this.getClass().getProtectionDomain().getCodeSource().getLocation().getPath();
        currentPath = new File(new File(currentPath).getParent()).getParent();
        
        String uuid = BM2PStringUtil.getUUID();
        // 这是生成的html文件名, uuid.html  (根目录下)
        String htmlName =currentPath + "//" +uuid + ".html";
        
        pw.flush();
        FileOutputStream fos =new FileOutputStream(htmlName);//把jsp输出的内容写到xxx.html
        os.writeTo(fos);
        fos.close();
        //生成的HTML文件
        File file = new File(currentPath + "//" +uuid + ".html");
        System.out.println("生成HTML文件:" + file.getAbsolutePath());


        //生成的pdf文件路径,uuid.pdf(根目录下)
        String pdfPath = currentPath + "\\" + uuid + ".pdf";
        Html2PdfUtil.convertHtmlToPdfCmd(file.getAbsolutePath(), pdfPath );
        System.out.println("生成PDF文件:" + pdfPath);


        //读取生成好的pdf文件,形成字节流
        //pdf file ->byte[]
        File pdfFile = new File(pdfPath);
        FileInputStream fis = null;
        ByteArrayOutputStream bos = null;
        byte[]  pdfBytes = null;
        try {
            fis = new FileInputStream(pdfFile);
            bos = new ByteArrayOutputStream();
            byte[] b = new byte[1024];
            int n;
            while ((n = fis.read(b)) != -1) {
                bos.write(b, 0, n);
            }
            if(bos!=null) {
                pdfBytes = bos.toByteArray();
            }
        } catch (Exception e1) {
        log.error(e1);
        }finally {
            if(bos!=null) {
                try {
                    bos.close();
                } catch (IOException e) {
                log.error(e);
                }
            }
            if(fis!=null) {
                try {
                    fis.close();
                } catch (IOException e) {
                log.error(e);
                }
            }
        }
        //调用打印机服务
        System.out.println("目标打印机名称:" + printerName);
        ServerPrintUtil.startPrintPdfThread(pdfBytes, printerName);        
        
        //记录打印履历及数据
        Tfmbdc1 his = new Tfmbdc1();
        his.setPrintReportId(printReportId);
        his.setKeyword(keyword);
        his.setFormEname(formEname);
        his.setButtonEname(buttonEname);
        //获取返回的打印ID
        his.setPrintId(request.getAttribute(BM2PReportConstants.COL_PRINT_ID).toString());
        his.setOperaId(BM2PStringUtil.getUUID());
        
        Tfmbdc2 data = new Tfmbdc2();
        //获取返回的业务数据json
        data.setDataJson(request.getAttribute(BM2PReportConstants.COL_DATA_JSON).toString());
        FMManagerFactory.getMgrPrintReportHistory().addPrintReportHistory(his, data);
    }

}

public class ServerPrintThread implements Runnable {
private static final Logger log = LoggerFactory.getLogger(ServerPrintThread.class);

private byte[] buffer;
private PrintFileType fileType;
private String printerName;


/**
* 服务端打印线程
* @param buffer 待打印的字节流
* @param fileType 待打印的文件类型
*/
    public ServerPrintThread(byte[] buffer, PrintFileType fileType) {
        this.buffer = buffer;
        this.fileType = fileType;
        this.printerName = BM2PConstants.STRING_EMPTY;
    }
    
    /**
* 服务端打印线程
* @param buffer 待打印的字节流
* @param fileType 待打印的文件类型
* @param printerName 服务端配置的打印机名称
*/
    public ServerPrintThread(byte[] buffer, PrintFileType fileType, String printerName) {
        this.buffer = buffer;
        this.fileType = fileType;
        this.printerName = printerName;
    }


    @Override
    public void run() {
        try {
        if(this.fileType == PrintFileType.PDF){
        printPDF(this.buffer, this.printerName);
        }
        } catch (PlatException e) {
        log.error(e);
            //e.printStackTrace();
        }
    }
    
    /**
     * 打印PDF
     * @param buffer 待打印的pdf文件字节流
     * @param printerName 服务端配置的打印机名称
     * @throws Exception
     */
    private void printPDF(byte[] buffer, String printerName) throws PlatException{
    try{
        InputStream stream = new ByteArrayInputStream(buffer);

        PDDocument document = PDDocument.load(stream);
        System.out.println("doc"+document.getDocumentInformation());
        PrinterJob job = PrinterJob.getPrinterJob();
        //job.setPageable(new PDFPageable(document, Orientation.LANDSCAPE, true));

//        PrintRequestAttributeSet attr = new HashPrintRequestAttributeSet();
        //attr.add()

        // define custom paper
        Paper paper = new Paper();
        /**
         * DPI:72px/inch,A4 size(598 * 842);
         DPI:96px/inch,A4 size(794* 1123);
         DPI:120px/inch,A4 size(1487* 2105);
         DPI:150px/inch,A4 size(1240* 1754);
         DPI:300px/inch,A4 size(2480* 3508);
         */
        //paper.setSize(3508, 2480);
        //paper.setImageableArea(20, 0, paper.getWidth()-20, paper.getHeight()); // no margins
        //目前 横板无法居中,且较小
        //        PDPage page = new PDPage(PDRectangle.A4);
        //        page.setRotation(90);
        //        document.addPage(page);

        // custom page format
        PageFormat pageFormat = new PageFormat();
        pageFormat.setPaper(paper);
        //pageFormat.setOrientation(PageFormat.LANDSCAPE);//landscape
        //pageFormat.

        // override the page format
        Book book = new Book();
        // append all pages
        book.append(new PDFPrintable(document, Scaling.SCALE_TO_FIT),//, true, 300.0F, true),
                pageFormat, document.getNumberOfPages());
        job.setPageable(book);

        //如果设置了打印机名称,则按照打印机名称查询打印服务并使用
        //否则走默认打印机
        if(StringUtils.hasContent(printerName)){
        PrintService printService = this.getPrintService(printerName);
        if(printService != null){
        System.out.println("服务器存在打印机名称"+printerName);
        job.setPrintService(printService);
        }
        }
        
        //if(job.printDialog()) {//弹出打印机属性窗口
        job.print();
        //}

        document.close();
    }
    catch(Exception e){
    throw new PlatException(e.getMessage());
    }
    }
    
    
    /**
     * 根据打印机名称获取打印服务
     * @param printerName 打印机名称
     * @return 打印服务
     */
    private PrintService getPrintService(String printerName) {
        PrintService[] printServices = PrintServiceLookup.lookupPrintServices(null, null);
        for (PrintService printService : printServices) {
            if (printService.getName().trim().equals(printerName)) {
                return printService;
            }
        }
        return null;
    }
    
    /**
     * 后台打印支持的文件类型
     * 
     *
     */
    public enum PrintFileType{
    PDF
    }
}

//HTML转换PDF工具类(需要在客户端安装转换工具:wkhtmltox-0.12.4_msvc2015-win64:默认路径:c:/wkhtmltopdf)

public class Html2PdfUtil {


/**
* 将html转成PDF
* <p>该方法转出来的pdf格式上有瑕疵,暂未使用<p/>
* @param inputHTMLFileName
* @param outputPDFFile
* @throws Exception
*/
public static void convertHtmlToPdf(String inputHTMLFileName, String outputPDFFile) throws Exception {
FileOutputStream fos = new FileOutputStream(outputPDFFile);
PD4ML pd4ml = new PD4ML();
pd4ml.setPageInsets(new Insets(20, 10, 10, 10));
pd4ml.setHtmlWidth(950);
pd4ml.setPageSize(pd4ml.changePageOrientation(PD4Constants.A4));
pd4ml.useTTF("java:fonts", true);
pd4ml.setDefaultTTFs("KaiTi_GB2312", "KaiTi_GB2312", "KaiTi_GB2312");
pd4ml.enableDebugInfo();
pd4ml.render("file:" + inputHTMLFileName, fos);
}

/**
* 将html转成PDF
* @param srcHtmlPath html路径
* @param destPdfPath pdf生成路径
*/
public static void convertHtmlToPdfCmd(String srcHtmlPath, String destPdfPath) {
try {
//wkhtmltopdf软件安装目录/bin/wkhtmltopdf.exe  完整路径
//软件下载地址  https://wkhtmltopdf.org/downloads.html
//服务器默认路径  "C:\\wkhtmltopdf\\bin\\wkhtmltopdf.exe"   在业务参数管理中配置

//这里有点问题,理论上不应该引用FM相关方法,但这个安装路径也没有地方配置,借用业务参数配置
IBizPara paraMgr = FMManagerFactory.getMgrBizPara();
String configPath = paraMgr.getBizParaDataByModuleIdAndParaId(BizModuleId.FM, BizParaId.WKHTMLTOPDF_INSTALLATION_PATH);
if (!StringUtils.hasContent(configPath)) {
throw new PlatException("未配置wkhtmltopdf软件路径");
}
String command = configPath;
command += "  --javascript-delay  2000 ";
command +=  " " + srcHtmlPath + " " + destPdfPath;
System.out.println("command:" + command);
final Process p = Runtime.getRuntime().exec(command);
final StringBuilder output = new StringBuilder();
new Thread(new Runnable() {
@Override
public void run() {
try {
try {
BufferedReader br = new BufferedReader(new InputStreamReader(p.getErrorStream()));
String line = br.readLine();
while (line != null) {
if (line.trim().length() > 0) {
output.append(line).append("\n");
}
line = br.readLine();
}
} finally {
if (p.getErrorStream() != null) {
p.getErrorStream().close();
}
}
} catch (IOException ex) {
ex.printStackTrace(System.err);
}
}
}).start();


new Thread(new Runnable() {
@Override
public void run() {
try {
try {
BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = br.readLine();
while (line != null) {
if (line.trim().length() > 0) {
output.append(line).append("\n");
}
line = br.readLine();
}
} finally {
if (p.getInputStream() != null) {
p.getInputStream().close();
}
}
} catch (IOException ex) {
ex.printStackTrace(System.err);
}
}
}).start();
p.waitFor();
String result = command + "\n" + output.toString() + output.toString();
System.out.print(result);//wkhtmltopdf程序运行时的软件输出,保存pdf的过程,可以选择不打印
} catch (Exception e) {
throw new PlatException(e.getMessage());
}
}

}



/**
 * 通过服务端打印工具类
 * 
 *
 */
public class ServerPrintUtil {

/**
* 启动打印PDF
* <p>不指定打印机,则为默认打印机<p/>
* @param printByte 待打印的PDF文件字节流
*/
public static void startPrintPdfThread(byte[] printByte){
ServerPrintThread printThread = new ServerPrintThread(printByte, PrintFileType.PDF);
Thread thread = new Thread(printThread);
        thread.start();
}


/**
* 启动打印PDF
* @param printByte 待打印的PDF文件字节流
* @param printerName 服务端配置的打印机名称
*/
public static void startPrintPdfThread(byte[] printByte, String printerName){
ServerPrintThread printThread = new ServerPrintThread(printByte, PrintFileType.PDF, printerName);
Thread thread = new Thread(printThread);
        thread.start();
}
}



  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
首先引入一个WebBrowser在需要打印的页面,可以直接添加: 复制代码 代码如下: <object id="WebBrowser" classid=CLSID:8856F961-340A-11D0-A96B-00C04FD705A2 height="0" width="0"> </object> 2 .页面设置和打印预览 如下所示,直接调用即可 复制代码 代码如下: document.all.WebBrowser.ExecWB(6,6) 直接打印 document.all.WebBrowser.ExecWB(8,1) 页面设置 document.all.WebBrowser.ExecWB(7,1) 打印预览 3 隐藏不打印的页面元素和分页 CSS 有个Media 属性,可以分开设置打印和显示的格式。 如 <style media="print" type="text/css"> …</style> 中间的格式将只在打印时起作用,不会影响显示界面。 所以可以设定 <style media="print" type="text/css"> .Noprint{display:none;} .PageNext{page-break-after: always;} </style> 然后给不想打印的页面元素添加: class="Noprint" ,那就不会出现在打印打印预览中了。 想分页的地方添加: <div class="PageNext"></div> 就可以了。 4.打印页面的特定部分 通过将需要打印的特定部分另建一个页面,然后装入主页面的一个IFrame中,再调用IFrame的打印方法,只打印IFrame中的内容实现的。 如: <iframe visible" name="FrameId" width="100%" height="30%" src="NeedPrintedPage.asp"></iframe> 下面的pringFrame js函数将只打印Iframe中的内容,可以直接引用使用,如printFrame(FrameId); 复制代码 代码如下: window.print = printFrame; // main stuff function printFrame(frame, onfinish) { if ( !frame ) frame = window; function execOnFinish() { switch ( typeof(onfinish) ) { case "string": execScript(onfinish); break;
重点: <OBJECT id=WebBrowser classid=CLSID:8856F961-340A-11D0-A96B-00C04FD705A2 height=0 width=0 VIEWASTEXT> </OBJECT> <input type=button value=打印 " class= "NOPRINT "> <input type=button value=直接打印 " class= "NOPRINT "> <input type=button value=页面设置 " class= "NOPRINT "> <input type=button value=打印预览 " class= "NOPRINT "> 注意: 1、CSS对打印的控制: <!--media=print 这个属性可以在打印时有效--> <style media=print> .Noprint{display:none;} .PageNext{page-break-after: always;} </style> Noprint样式可以使页面上的打印按钮等不出现在打印页面上,这一点非常重要,因为它可以用最少的代码完成最需要的功能 PageNext样式可以设置分页,在需要分页的地方 就OK了,呵呵 2、表格线粗细的设置,更是通过样式表: <style> .tdp { border-bottom: 1 solid #000000; border-left: 1 solid #000000; border-right: 0 solid #ffffff; border-top: 0 solid #ffffff; } .tabp { border-color: #000000; border-collapse:collapse; } </style> 或者: <style> .TdCs1 { border:solid windowtext 1.0pt; } .TdCs2 { border:solid windowtext 1.0pt; border-left:none; } .TdCs3 { border-top:none; border-left:solid windowtext 1.0pt; border-bottom:solid windowtext 1.0pt; border-right:solid windowtext 1.0pt; } .TdCs4 { border-top:none; border-left:none; border-bottom:solid windowtext 1.0pt; border-right:solid windowtext 1.0pt; } .underline { border-top-style: none; border-right-style: none; border-bottom-style: solid; border-left-style: none; border-bottom-color: #000000; } </style> 1、控制 "纵打 "、 横打”和“页面的边距。 (1) [removed] function SetPrintSettings() {  // -- advanced features  factory.printing.SetMarginMeasure(2) // measure margins in inches  factory.SetPageRange(false, 1, 3) // need pages from 1 to 3  factory.printing.pri
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值