wk-pdf报告生成

Posted by 小马哥 on 08-29,2019

docker构建wk基础镜像

FROM openjdk:8
MAINTAINER haijunsun haijunsun2@creditease.cn
USER root
COPY Shanghai /usr/share/zoneinfo/Asia/Shanghai

RUN apt-get update \
    && apt-get install -y curl xfonts-base xfonts-75dpi libjpeg62-turbo libx11-6 libxcb1 libxext6 libxrender1\
    && apt-get clean \
    && curl "https://downloads.wkhtmltopdf.org/0.12/0.12.5/wkhtmltox_0.12.5-1.stretch_amd64.deb" -L -o "wkhtmltopdf.deb" \
    && dpkg -i ./wkhtmltopdf.deb \
    &&  apt-get install -f \
    && rm -rf wkhtmlto* \
    && ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
    && echo 'Asia/Shanghai' >/etc/timezone

COPY Alibaba-PuHuiTi-Regular.ttf /usr/share/fonts/chinese/TrueType/simsun.ttc
  1. FROM openjdk:8 为基础镜像
  2. COPY Shanghai /usr/share/zoneinfo/Asia/Shanghai 时区文件覆盖
  3. RUN apt-get update.... 为基础镜像安装wk服务
  4. COPY Alibaba-PuHuiTi-Regular.ttf /usr/share/fonts/chinese/TrueType/simsun.ttc 字体支持

生成pdf命令

/usr/local/bin/wkhtmltopdf  --page-height 378.2 --page-width 272 --javascript-delay 1000 --encoding utf-8 http://app.bocheng-insurance.com/front/planPdfReports/?reportCode=PLAN20190719194343P1tFEB /app/o2o_doc/pdf/0719.pdf

--javascript-delay 为页面异步执行等待时间

http://app.bocheng-insurance.com/front/planPdfReports/?reportCode=PLAN20190719194343P1tFEB为需要生成pdf的页面地址

/app/o2o_doc/pdf/0719.pdf 保单pdf的地址

注意事项

  • java调用命令 线程堵塞

    try {
      log.info("执行生成pdf,srcPath={},destPath={},执行的命令信息:{}", srcPath, targetPath, cmd.toString());
      Process proc = Runtime.getRuntime().exec(cmd.toString());
      proc.waitFor();
    } catch (Exception e) {
      log.error("生成pdf文件异常", e);
      throw new GlobalException(BasicCodeMsg.SERVER_ERROR.setMsg("生成pdf文件异常"));
    }
    

    存在风险:

    1. waitFor:等待子进程执行结束,或者已终止子进程,此方法立即返回。
    2. 当RunTime对象调用exec方法后,jvm会创建一个子进程,该子进程与jvm建立三个管道连接:标准输入流、标准输出流、标准错误流。假设该子进程不断向标准输入流、标准输出流写数据,而jvm不读取的话,会导致缓冲区塞满而无法继续写数据,最终堵塞在waitFor这里。
  • java调用命令正确执行

    try {
      log.info("执行生成pdf,srcPath={},destPath={},执行的命令信息:{}", srcPath, targetPath, cmd.toString());
      Process proc = Runtime.getRuntime().exec(cmd.toString());
      // 标准错误流(必须写在 waitFor 之前)
      HtmlToPdfInterceptor error = new HtmlToPdfInterceptor(proc.getErrorStream());
      // 标准输入流(必须写在 waitFor 之前)
      HtmlToPdfInterceptor output = new HtmlToPdfInterceptor(proc.getInputStream());
      error.start();
      output.start();
      proc.waitFor();
    } catch (Exception e) {
      log.error("生成pdf文件异常", e);
      throw new GlobalException(BasicCodeMsg.SERVER_ERROR.setMsg("生成pdf文件异常"));
    }
    

    HtmlToPdfInterceptor.java

    @Slf4j
    public class HtmlToPdfInterceptor extends Thread {
        private InputStream is;
        public HtmlToPdfInterceptor(InputStream is){
            this.is = is;
        }
        public void run(){
            try{
                InputStreamReader isr = new InputStreamReader(is, "utf-8");
                BufferedReader br = new BufferedReader(isr);
                String line = null;
                while ((line = br.readLine()) != null) {
                    //输出内容
                    log.info(line);
                }
            }catch (IOException e){
                e.printStackTrace();
            }
        }
    }