需求:点击按钮,将相关内容生成pdf下载下来
问题1:之前项目封装好的下载文件方法不携带token
我尝试新写了一个方法,携带token
问题2:此时出现了跨域问题
我分别尝试在controller类上和方法上加@CrossOrigin(origins = "*")都无济于事。
我在拦截器里打了断点,发现浏览器发的请求头根本获取不到。
原因是跨域请求浏览器会先发起一个预检请求,此时我们应该拦截并允许跨域
跨域问题解决
==========================0
生成pdf需要引入这俩依赖
java
// https://mvnrepository.com/artifact/org.thymeleaf/thymeleaf
implementation("org.thymeleaf:thymeleaf:3.1.3.RELEASE")
// https://mvnrepository.com/artifact/org.xhtmlrenderer/flying-saucer-pdf
implementation("org.xhtmlrenderer:flying-saucer-pdf:9.13.1")
thymeleaf+Flying Saucer(将html转换为pdf)
java
package com.jiangee.environment.utils;
import com.lowagie.text.pdf.BaseFont;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;
import org.xhtmlrenderer.css.parser.property.PageSize;
import org.xhtmlrenderer.pdf.ITextRenderer;
import java.io.ByteArrayOutputStream;
import java.util.Locale;
import java.util.Map;
@Component
public class ThymeleafPdf {
@Resource
private TemplateEngine templateEngine;
public byte[] generatePdf(String templateName, Map<String, Object> data) {
Context context = new Context();
context.setVariables(data);
String htmlContent = templateEngine.process(templateName, context);
try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
ITextRenderer renderer = new ITextRenderer();
renderer.setDocumentFromString(htmlContent);
// 获取resources/下的文件
//加载本地字体,不然不显示中文
String fontPath = this.getClass().getClassLoader().getResource("font/simsun.ttc").getPath();
renderer.getFontResolver().addFont(fontPath, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
renderer.layout();
renderer.createPDF(outputStream);
return outputStream.toByteArray();
} catch (Exception e) {
throw new RuntimeException("Error generating PDF", e);
}
}
}
java
public void exportHandoverSheet(String batchId, HttpServletResponse response) {
// 准备数据
Map<String, Object> data = new HashMap<>();
Map<String, Object> invoice = new HashMap<>();
invoice.put("number", "INV-2023-001");
invoice.put("date", LocalDate.now());
invoice.put("from", "ABC Company\n123 Main St\nNew York, NY 10001");
invoice.put("to", "XYZ Client\n456 Oak Ave\nBoston, MA 02108");
data.put("invoice", invoice);
// 生成PDF
byte[] pdfBytes = thymeleafPdf.generatePdf("invoice", data);
// 3. 设置响应头
response.setContentType(MediaType.APPLICATION_PDF_VALUE);
response.setHeader("Content-Disposition", "attachment; filename=invoice.pdf");
response.setContentLength(pdfBytes.length);
// 4. 写入响应流
try (OutputStream out = response.getOutputStream()) {
out.write(pdfBytes);
out.flush();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
注:templateName是html名字,
此时运行报错:找不到TemplateEngine,
需要再加一个依赖
go
// https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-thymeleaf
implementation("org.springframework.boot:spring-boot-starter-thymeleaf:3.5.2")
html
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta charset="UTF-8"/>
<title>Invoice</title>
<style>
@page {
size: A4 landscape; /* 横向A4 */
margin: 1cm;
}
body { font-family: SimSun, sans-serif; margin: 20px; }
.header { text-align: center; margin-bottom: 30px; }
.info { margin-bottom: 20px; }
table { width: 100%; border-collapse: collapse; margin-bottom: 20px; }
th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
th { background-color: #f2f2f2; }
.total { text-align: right; font-weight: bold; }
</style>
</head>
<body>
<div class="header">
<h2>地下水环境调查送检样品交接表单</h2>
<hr/>
</div>
<div class="info">
<p><strong>From:</strong> <span th:text="${invoice.from}"></span></p>
<p><strong>To:</strong> <span th:text="${invoice.to}"></span></p>
</div>
<table>
<thead>
<tr>
<th>Description</th>
<th>Quantity</th>
<th>Unit Price</th>
<th>Amount</th>
</tr>
</thead>
<tbody>
<tr th:each="item : ${invoice.items}">
<td th:text="${item.description}"></td>
<td th:text="${item.quantity}"></td>
<td th:text="${'$' + #numbers.formatDecimal(item.unitPrice, 1, 2)}"></td>
<td th:text="${'$' + #numbers.formatDecimal(item.quantity * item.unitPrice, 1, 2)}"></td>
</tr>
</tbody>
</table>
<div class="total">
<h3>Total: <span th:text="${'$' + #numbers.formatDecimal(invoice.total, 1, 2)}"></span></h3>
</div>
</body>
</html>