RestPack Java实现Html转PDF文件

最近公司需要将前端一个图表统计导出为pdf。前端导出显示的pdf还是可以的,但是将会导致页面不可用与卡死状态。所以由后端寻找解决方案。

以下为解决方案调研

https://www.cnblogs.com/IT-study/p/13706690.html

由于自己开发一个公共的导出pdf功能比较费时费力,而且导出过程中也遇到了各种样式问题。考虑再三决定使用第三方导出来解决这个问题。

好处:接入简单给个H5url即可,无需要考虑导出中遇到的写出的样式与排版问题

坏处:无法做到完全自定义。拿restPack举例子 ,导出长图无法自定义宽度,目前导出有1280px宽度,业务需要手机预览宽度只要 A6纸的规格即可。也可能可以通过js、css参数去解决,我没找到对应的方法。

官网https://restpack.io/

解决思路

1.将一个可访问的H5URL转换为Pdf文件

2.将Pdf文件写到页面

H5URL转换为Pdf文件

 1 @Component
 2 public class H5UrlExportPdf {
 3 
 4 
 5     @Value("${restpack.token}")
 6     private String token = "HA5jLSVtSnjl3fmlhPgTg7rPRE4OnywDvh1CrbanXmpBvNqA";
 7 
 8 
 9     /**
10      * https://restpack.io/html2pdf/docs
11      */
12     public ReturnRestPackPdf exportPdf(RestPackPdfParameters restpackPdfParameters) throws IOException {
13 
14 
15         ReturnRestPackPdf returnRestPackPdf;
16 
17         //请求URL
18         String reqUrl = "https://restpack.io/api/html2pdf/v6/convert";
19         StringBuilder stringBuilder = new StringBuilder();
20 
21         //地址需要encode
22         String firstP = "url";
23         stringBuilder.append(firstP).append("=").append(restpackPdfParameters.getUrl());
24 
25         Map<String, String> describe = BeanHelper.describe(restpackPdfParameters);
26         describe.forEach((name, val) -> {
27 
28             if (!firstP.equalsIgnoreCase(name)) {
29                 stringBuilder.append("&").append(name).append("=").append(val);
30             }
31         });
32 
33         System.out.println(stringBuilder.toString());
34 
35         byte[] postData = stringBuilder.toString().getBytes(StandardCharsets.UTF_8);
36         HttpURLConnection con = null;
37 
38         try {
39 
40             URL myUrl = new URL(reqUrl);
41             con = (HttpURLConnection) myUrl.openConnection();
42 
43             con.setDoOutput(true);
44             con.setRequestMethod("POST");
45             con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
46             con.setRequestProperty("x-access-token", token);
47 
48             try (DataOutputStream wr = new DataOutputStream(con.getOutputStream())) {
49                 wr.write(postData);
50             }
51 
52             StringBuilder content;
53 
54             try (BufferedReader in = new BufferedReader(
55                     new InputStreamReader(con.getInputStream()))) {
56 
57                 String line;
58                 content = new StringBuilder();
59 
60                 while ((line = in.readLine()) != null) {
61                     content.append(line);
62                     content.append(System.lineSeparator());
63                 }
64             }
65 
66             returnRestPackPdf = JSONObject.parseObject(content.toString(), ReturnRestPackPdf.class);
67 
68         } finally {
69             if (con != null) {
70                 con.disconnect();
71             }
72         }
73 
74         return returnRestPackPdf;
75     }
76 
77 
78 }

H5URL导出文档入参

 1 @Data
 2 public class RestPackPdfParameters implements Serializable{
 3 
 4     private static final long serialVersionUID = 1L;
 5 
 6 
 7     /**
 8      * 需要导出文档H5URL
 9      * The URL of web page, including the protocol that you want to capture.
10      * Example: http://example.com
11      */
12     private String url;
13 
14 
15     /**
16      * Return a JSON response with the resulting image's URL instead of the image itself.
17      * Default: false
18      */
19     private Boolean json = true;
20 
21 
22     /**
23      * Page size for created document
24      *
25      * Default: Full
26      * Pattern: A0 | A1 | A2 | A3 | A4 | A5 | A6 | Legal | Letter | Tabloid | Ledger | Full
27      *
28      * Legal:width 816 多张图片阶段
29      * Letter:width 816 多张图片阶段
30      * Tabloid:width 1056 多张图片阶段
31      * Ledger:width 1632 多张图片阶段
32      * Full:width 1280 一张图片
33      */
34     private String pdf_page="Full";
35 
36     public RestPackPdfParameters() {
37     }
38 
39     public RestPackPdfParameters(String url) {
40         this.url = url;
41     }
42 }

H5URL导出文档返回参数

 1 @Data
 2 public class ReturnRestPackPdf implements Serializable{
 3 
 4     private static final long serialVersionUID = 1L;
 5 
 6 
 7     private Boolean cached;
 8     private String content_type;
 9     /** pdf文件类型地址 */
10     private String file;
11     private Integer height;
12     private Integer width;
13     /** pdf图片类型地址 */
14     private String image;
15     private String length;
16     private String remote_status;
17     private String run_time;
18     private String url;
19 
20 }

将文件写到页面

 1     private void downFileHtml(String name, @RequestParam(value = "fileUrl", required = false) String fileUrl, HttpServletResponse response, Boolean useName) {
 2         BufferedInputStream bis = null;
 3         BufferedOutputStream bos = null;
 4         OutputStream output = null;
 5         try {
 6             log.info("downLoadFileStart:" + fileUrl);
 7             response.setContentType("application/octet-stream; charset=UTF-8");
 8             if (useName) {
 9 
10             } else {
11                 String ext = fileUrl.substring(fileUrl.lastIndexOf("."));
12                 name = name + ext;
13                 name = URLDecoder.decode(name, "UTF-8");
14             }
15 
16             response.setHeader("Content-Disposition", "attachment;fileName="" + new String(name.getBytes("GBK"), "ISO8859-1") + """);
17 
18             URL url = new URL(fileUrl);
19             bis = new BufferedInputStream(url.openStream());
20             output = response.getOutputStream();
21             bos = new BufferedOutputStream(output);
22             log.info("downLoadFileCopyStream:" + fileUrl);
23             byte[] buff = new byte[2048];
24             int bytesRead;
25             while (-1 != (bytesRead = bis.read(buff, 0, buff.length))) {
26                 log.info("downLoadFileCopyStreamDetail:" + bytesRead);
27                 bos.write(buff, 0, bytesRead);
28             }
29             log.info("downLoadFileEnd:" + fileUrl);
30         } catch (Exception e) {
31             log.error("downLoadFileError:" + fileUrl + ":error:" + e.getMessage());
32             e.printStackTrace();
33         } finally {
34             try {
35                 if (bos != null) {
36                     bos.flush();
37                     bos.close();
38                 }
39                 if (bis != null) {
40                     bis.close();
41                 }
42                 if (output != null) {
43                     output.close();
44                 }
45             } catch (IOException e) {
46                 e.printStackTrace();
47             }
48         }
49     }

使用事项

1.url 为转换pdf的页面地址,改地址必须能直接访问(无登录功能)

2.pdf_page 有几个页面规格 A0 | A1 | A2 | A3 | A4 | A5 | A6 | Legal | Letter | Tabloid | Ledger | Full 。Full可导出一张长图,但是宽度不可定。其他的规格与A4类似,导出的是多张图片。

3.pdf_width 、pdf_height 可自定义页面规格。一旦pdf_page设置,pdf_width pdf_height必须为空。

4.一旦付费成功 css、js 可进行调节生成pdf文件产生的样式问题。

5.我们需要导出一整张图片,但是一整张图的宽度不可自定义。导出的宽度为1280px,手机上显示只需要800px。目前这个问题还不知道怎么解决

  

原文地址:https://www.cnblogs.com/IT-study/p/13738157.html