• Spring boot 通过 wkhtmltopdf 实现URL转PDF


    一 、前言

    本文将会基于 SpringBoot版本:2.3.8.RELEASE 使用 wkhtmltopdf 转换成 pdf文件。
    在使用wkhtmltopdf之前 同事有尝试用itext创建的PDF我觉得兼容性不好,然后参考其他博客觉得wkhtmltopdf兼容性在样式上好一些

    tips:仅作为学习笔记记录

    二 、安装wkhtmltopdf

    2.1 环境

    安装包: Github地址
    先查看自己安装wkhtmltopdf的环境
    例子:
    我这边服务是在k8s的容器里面,进入容器查看

    cat /etc/os-release
    PRETTY_NAME="Debian GNU/Linux 10 (buster)"
    NAME="Debian GNU/Linux"
    VERSION_ID="10"
    VERSION="10 (buster)"
    VERSION_CODENAME=buster
    ID=debian
    HOME_URL="https://www.debian.org/"
    SUPPORT_URL="https://www.debian.org/support"
    BUG_REPORT_URL="https://bugs.debian.org/"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    版本:buster
    点击上面的安装包链接 ,选择 0.12.5版本 Assets 里面有两个关于buster安装的包

    • wkhtmltox_0.12.5-1.buster_amd64.deb
    • wkhtmltox_0.12.5-1.buster_i386.deb

    2.2 安装

    把我们准备好的 wkhtmltox_0.12.5-1.buster_amd64.deb 文件放入容器

    kubectl cp ./wkhtmltox_0.12.5-1.buster_amd64.deb app-dataupload-548df6b957-k287b:./wkhtmltox_0.12.5-1.buster_amd64.deb -n namespace
    
    • 1

    进入容器后发现已经有了文件,切换到文件目录

    // 安装 wkhtmltox
    dpkg -i wkhtmltox_0.12.5-1.buster_amd64.deb
    
    • 1
    • 2

    安装错误这里出现需要安装的依赖

    // 尝试安装
    apt-get install -y fontconfig libfreetype6 libjpeg62-turbo libpng16-16 libx11-6 libxcb1 libxext6 libxrender1 xfonts-75dpi xfonts-base
    
    // 报错
    E: Package 'fontconfig' has no installation candidate
    E: Package 'libfreetype6' has no installation candidate
    E: Package 'libjpeg62-turbo' has no installation candidate
    E: Package 'libpng16-16' has no installation candidate
    E: Package 'libx11-6' has no installation candidate
    E: Package 'libxcb1' has no installation candidate
    E: Package 'libxext6' has no installation candidate
    E: Package 'libxrender1' has no installation candidate
    E: Package 'xfonts-75dpi' has no installation candidate
    E: Package 'xfonts-base' has no installation candidate
    
    // 更新apt-get
    apt-get update
    
    // 连接超时
    Get:1 http://security.debian.org/debian-security buster/updates InRelease [34.8 kB]                      
    Get:2 http://security.debian.org/debian-security buster/updates/main amd64 Packages [379 kB]            
    Err:3 http://deb.debian.org/debian buster InRelease                                                                                                                                                                                    
      Could not connect to deb.debian.org:80 (151.101.110.132), connection timed out
    Err:4 http://deb.debian.org/debian buster-updates InRelease
      Unable to connect to deb.debian.org:http:
    Fetched 414 kB in 30s (13.7 kB/s)
    Reading package lists... Done
    W: Failed to fetch http://deb.debian.org/debian/dists/buster/InRelease  Could not connect to deb.debian.org:80 (151.101.110.132), connection timed out
    W: Failed to fetch http://deb.debian.org/debian/dists/buster-updates/InRelease  Unable to connect to deb.debian.org:http:
    W: Some index files failed to download. They have been ignored, or old ones used instead.
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    2.3 解决报错

    两个问题:

    1. 安装时缺少关键依赖包
    2. apt-update 连接不上

    首先 apt-update 更换成国内源 ,之后再去安装依赖。这里需要注意的是打包成Docker镜像的时候需要提前安装好依赖
    再去安装wkhtmltox,不然打包成镜像会失败。

    // 换成国内源
    echo > /etc/apt/sources.list 
    echo -e "deb http://mirrors.aliyun.com/debian/ stretch main non-free contrib \ndeb-src http://mirrors.aliyun.com/debian/ stretch main non-free contrib \ndeb http://mirrors.aliyun.com/debian-security stretch/updates main \ndeb-src http://mirrors.aliyun.com/debian-security stretch/updates main \ndeb http://mirrors.aliyun.com/debian/ stretch-updates main non-free contrib \ndeb-src http://mirrors.aliyun.com/debian/ stretch-updates main non-free contrib \ndeb http://mirrors.aliyun.com/debian/ stretch-backports main non-free contrib \ndeb-src http://mirrors.aliyun.com/debian/ stretch-backports main non-free contrib" > /etc/apt/sources.list 
    // 更新
    apt-get update -y
    // 安装缺少依赖库
    apt-get install -y fontconfig libfreetype6 libjpeg62-turbo libpng16-16 libx11-6 libxcb1 libxext6 libxrender1 xfonts-75dpi xfonts-base
    // 安装包
    dpkg -i wkhtmltox_0.12.5-1.buster_amd64.deb
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    还有需要注意的是:
    Dockerfile 中如果加 -e 选项会将其当作字符串拼接在前面
    这样转换的pdf 中文会乱码 需要将字体放在 /usr/share/fonts/ 目录下

    2.4 DockerFile参考

    # 基础镜像 包含jdk
    FROM xxxx
    COPY wkhtmltox_0.12.5-1.buster_amd64.deb wkhtmltox_0.12.5-1.buster_amd64.deb
    COPY font/ /usr/share/fonts/
    RUN echo > /etc/apt/sources.list && echo "deb http://mirrors.aliyun.com/debian/ stretch main non-free contrib \ndeb-src http://mirrors.aliyun.com/debian/ stretch main non-free contrib \ndeb http://mirrors.aliyun.com/debian-security stretch/updates main \ndeb-src http://mirrors.aliyun.com/debian-security stretch/updates main \ndeb http://mirrors.aliyun.com/debian/ stretch-updates main non-free contrib \ndeb-src http://mirrors.aliyun.com/debian/ stretch-updates main non-free contrib \ndeb http://mirrors.aliyun.com/debian/ stretch-backports main non-free contrib \ndeb-src http://mirrors.aliyun.com/debian/ stretch-backports main non-free contrib" > /etc/apt/sources.list && apt-get update -y && apt-get install -y fontconfig libfreetype6 libjpeg62-turbo libpng16-16 libx11-6 libxcb1 libxext6 libxrender1 xfonts-75dpi xfonts-base && dpkg -i wkhtmltox_0.12.5-1.buster_amd64.deb
    MAINTAINER xxx
    ADD *.jar app.jar
    EXPOSE 80
    ENTRYPOINT ["java","-jar", "-Dspring.profiles.active=test","/app.jar"]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    三、Java 使用

      /**
      * url转换成PDF
      * @param url 地址
      * @param saveFilePath 存储PDF的地址
      */
      @SneakyThrows({Exception.class})
      public static void url2Pdf(String url, String saveFilePath) {
          String command = String.format("%s %s %s", "wkhtmltopdf", url, saveFilePath);
          Process process = null;
          try {
              process = Runtime.getRuntime().exec(command);
          } catch (IOException e) {
              throw new Exception("执行命令失败!");
          }
          // 等待当前命令执行完,再往下执行
          process.waitFor();
          log.info("=======【地址 {} 】======== FINISH: [{}] ===============", url,command);
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    四、总结

    到这里基本上应该可以使用 wkhtmltox
    总体的思路就是 把之前的jdk镜像和 wkhtmltox集成 制作成新的基础镜像
    然后在项目里通过cmd命令去执行 url 转换成PDF

    文章是我后面回忆时候写的如果存在问题 欢迎批评指正~ 谢谢
    有些复杂的页面可能无法支持,相对简单些的 兼容性应该可以的,对于我自己的需求基本满足

  • 相关阅读:
    vue跨域proxy详解(下)
    java读取csv文件或者java读取字符串,找出引号内容,采用正则表达式书写
    干货 | 一文搞定 pytest 自动化测试框架
    Axure原型设计工具怎么样?有替代软件吗?
    DDD项目落地之充血模型实践
    Go语言入门篇
    【机器学习】线性回归【上】朴素最小二乘估计
    关于#后端#的问题,请各位专家解答!
    连花清瘟胶囊新冠应用 大健康医药·李喜贵:微量元素作用解密
    你可需要的对象存储中间件《Minio使用》
  • 原文地址:https://blog.csdn.net/github_38787615/article/details/127551960