Java 使用 wkhtmltopdf 生成 PDF 遇到的几个坑
wkhtmltopdf 使用本地文件生成 PDF 失败
一般使用命令 wkhtmltopdf URL pdfPath
生成 PDF 文件,其中 URL 为 GET 请求地址。
但是笔者在做的项目是一个模板中心服务(后续代码整理好会上传到 Gitee),实现的功能是可以上传 Thymeleaf 的 HTML 模板文件,然后调用 GET 接口传入模板数据(Map 类型)后,直接返回生成的 PDF。既然使用 Map 传送模板数据,就不能使用 GET 请求了,一方面拼接 Map 比较麻烦,另一方面如果 Map 数据量过大可能超过 URL 长度限制。
印象中 wkhtmltopdf 可以通过本地文件转 PDF,遂尝试先调用 POST 接口将数据填充到模板中,拿到返回的 HTML 后写入到临时文件中,然后通过 wkhtmltopdf HTML pdfPath
将 HTML 文件转换为 PDF 文件。
但是程序怎么弄都不行,就是会报错:
2022-12-13 16:36:59,873 INFO HtmlToPdfInterceptor ===> Loading page (1/2)
2022-12-13 16:36:59,873 INFO HtmlToPdfInterceptor ===> [> ] 0%
2022-12-13 16:36:59,873 INFO HtmlToPdfInterceptor ===> [======> ] 10%
2022-12-13 16:37:02,427 INFO HtmlToPdfInterceptor ===> Error: Failed to load http://d/Source/secp-template-center/secp-template-service/target/classes/templates/thymeleaf/Seeds-Pro/test.html, with network status code 3 and http status code 0 - Host d not found
2022-12-13 16:37:02,428 INFO HtmlToPdfInterceptor ===> Error: Failed loading page http:///D:/Source/secp-template-center/secp-template-service/target/classes/templates/thymeleaf/Seeds-Pro/test.html (sometimes it will work just to ignore this error with --load-error-handling ignore)
2022-12-13 16:37:02,428 INFO HtmlToPdfInterceptor ===> Exit with code 1 due to network error: HostNotFoundError
但是同样的命令,直接在 cmd 里面就可以执行:
搜索无果,官方 GitHub 也没找到有用信息,喊同事来看也没发现问题,后来他在自己的 Mac 上拉代码跑了遍,发现正常,而我用的是公司发的 ThinkPad。。。
事后分析,是路径分隔符的问题,wkhtmltopdf 对 Windows 下的路径分隔符兼容性不好,通过 Path.of(first, more)
静态方法结合 File.separator
构造路径就没有问题了。
又一个生成失败问题
也是同样的命令,cmd 和 sh 里面都可以执行,服务器上就会报错:
2023-04-10 11:07:47,752 INFO CMD----> wkhtmltoimage --quality 40 "/home/templates/thymeleaf/Seeds/1645260793308119040.html" "/home/templates/thymeleaf/Seeds/1645260793308119040.png"
2023-04-10 11:07:47,783 INFO HtmlToPdfInterceptor ===> Loading page (1/2)
2023-04-10 11:07:47,783 INFO HtmlToPdfInterceptor ===> [> ] 0%
2023-04-10 11:07:47,784 INFO HtmlToPdfInterceptor ===> [======> ] 10%
2023-04-10 11:07:47,835 INFO HtmlToPdfInterceptor ===> Error: Failed to load http://home/templates/thymeleaf/Seeds/1645260793308119040.html", with network status code 3 and http status code 0 - Host home not found
2023-04-10 11:07:47,835 INFO HtmlToPdfInterceptor ===> Error: Failed loading page http:/home/templates/thymeleaf/Seeds/1645260793308119040.html" (sometimes it will work just to ignore this error with --load-error-handling ignore)
2023-04-10 11:07:47,835 INFO HtmlToPdfInterceptor ===> Exit with code 1 due to network error: HostNotFoundError
注意看倒数第三行 Failed to load http://home/templates/thymeleaf/Seeds/1645260793308119040.html"
,路径 /home
前面的双引号没有了,本来怀疑是 wkhtml 的问题,后来根据关键词 Runtime.exec 双引号
检索,发现一篇好文 java getRuntime().exec 带符号的命令 无法执行 解决方法,解决方法不能直接使用命令字符串,而要使用命令字符串数组。
OpenFeign 不支持 HttpServletResponse
问题
模板中心服务返回的 HttpServletResponse
,OpenFeign 不支持,只能将文件转为 Base64 返回,另外的方法是使用 RestTemplate
或者 HttpClient
。
使用方 getOutputStream() has already been called for this response 错误
使用方通过 GET 请求获取 PDF 的时候,返回值必须是 void,因为返回文件使用的是 HttpServletResponse
,而 SpringMVC 返回的时候也会使用 response 的 getOutputStream()
方法,而该方法只能调用一次。
本文作者:ageovb
本文链接:https://www.cnblogs.com/ageovb/p/16980749.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步