java导出pdf
wps直接编辑pdf文件,不用java里面用word模板
点击查看代码
@Override
public void downloadTransferZipV2(KsxxDto dto, HttpServletResponse response, HttpServletRequest request) {
String nd = dto.getNd();
if (StringUtils.isBlank(nd)) {
throw new CloudException("请设置招生年度");
}
// 查询需要导出的考生
dto.setYear(nd);
List<Ksxx> ksxxList = ksxxMapper.queryLqKsxx(dto);
// // 查询调档函相关数据
// SjzdExample example = new SjzdExample();
// example.createCriteria().andCFlbmEqualTo("ddhxx").andCSfscEqualTo(CodeConstants.SF_F);
// List<Sjzd> ddhList = sjzdMapper.selectByExample(example);
// Map<String, Sjzd> ddhMap = new HashMap<>();
// if (ddhList != null && !ddhList.isEmpty()) {
// ddhMap = ddhList.stream().collect(Collectors.toMap(Sjzd::getcBm, Function.identity(), (key1, key2) -> key2));
// }
// String schoolName = getSchoolName();
try (ZipOutputStream zos = new ZipOutputStream(response.getOutputStream())) {
for (Ksxx ksxx : ksxxList) {
ByteArrayOutputStream os = new ByteArrayOutputStream();
QrCodeVo vo = new QrCodeVo();
vo.setKsbh(ksxx.getKsbh());
vo.setXm(ksxx.getXm());
vo.setBmh(ksxx.getBmh());
vo.setZjhm(ksxx.getZjhm());
vo.setLx(ksxx.getLx());
vo.setYxdm(StringUtils.equals(ksxx.getLx(), CodeConstants.RYLX_TJ) ? ksxx.getTjYxsdm() : ksxx.getBkyxsm());
vo.setZydm(StringUtils.equals(ksxx.getLx(), CodeConstants.RYLX_TJ) ? ksxx.getTjZydm() : ksxx.getBkzydm());
vo.setXxfs(StringUtils.equals(ksxx.getLx(), CodeConstants.RYLX_TJ) ? ksxx.getTjXxfs() : ksxx.getBkxxfs());
vo.setXh(ksxx.getXh());
vo.setDaxh(ksxx.getDaxh());
String codeInfo = JSON.toJSONString(vo);
codeInfo = AESUtil.aesEncrypt(codeInfo, CodeConstants.AES_TOKEN);
String qrCodeBase64 = pdfUtils.getQrCodeBase64(codeInfo);
Map<String, Object> dataModel = new HashMap<>();
dataModel.put("nd", nd);
// dataModel.put("xxmc", getSchoolName());
dataModel.put("dwxx", UsualUtil.strIsEmpty(ksxx.getDaszdw()) ? "" : ksxx.getDaszdw() + ":");
dataModel.put("xm", ksxx.getXm());
// dataModel.put("rq1", "2025年7月5日");
// dataModel.put("rq2", "2025年5月20日");
// dataModel.put("yjdz", "浙江省杭州市钱塘区学源街998号浙江传媒学院行政楼202");
// dataModel.put("yzbm", "310018");
// dataModel.put("lxdh", "洪老师 0571-86832041");
dataModel.put("qrImage", qrCodeBase64);
dataModel.put("yxmc", StringUtils.equals(ksxx.getLx(),CodeConstants.KSXXLX_YZY) ? ksxx.getBkyxsmc() : ksxx.getTjYxsmc());
dataModel.put("zymc", StringUtils.equals(ksxx.getLx(),CodeConstants.KSXXLX_YZY) ? ksxx.getBkzymc() : ksxx.getTjZymc());
dataModel.put("yjfxmc", StringUtils.equals(ksxx.getLx(),CodeConstants.KSXXLX_YZY) ? ksxx.getYjfxmc() : ksxx.getTjYjfxmc());
String fileTemplate = pdfUtils.getPdfTempPath("ddh25050601.pdf");
pdfUtils.fillTemplate(dataModel, fileTemplate, os);
InputStream pdfImputStream = new ByteArrayInputStream(os.toByteArray());
zos.putNextEntry(new ZipEntry(ksxx.getXh() + "_" + ksxx.getXm() + ".pdf"));
byte[] buffer = new byte[ONE_THOUSAND_AND_TWENTY_FOUR];
writeStram(zos, buffer, pdfImputStream);
if (os != null) {
os.close();
}
}
zos.closeEntry();
zos.flush();
} catch (Exception e) {
log.error("生成二维码错误!", e);
e.printStackTrace();
}
}
点击查看代码
package com.yw.server.utils.tools;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import static com.google.zxing.client.j2se.MatrixToImageConfig.BLACK;
import static com.google.zxing.client.j2se.MatrixToImageConfig.WHITE;
@Slf4j
@Component
public class MyPdfUtils {
@Value("${win.fonts.song}")
private String songFonts;
/**
* 利用模板生成pdf
*
* @param o 写入的数据
* @param templatePath pdf模板路径
* @param fileName 文件名
* @param response 响应体
*/
public void fillTemplate(Map<String, Object> o, String templatePath, String fileName, HttpServletResponse response) throws Exception {
if (UsualUtil.strIsNotEmpty(fileName)) {
forwardToBrowser("application/x-msdownload", fileName, response);
}
fillTemplate(o, templatePath, response.getOutputStream());
}
public void fillTemplate(Map<String, Object> o, String templatePath , OutputStream os) throws Exception {
PdfReader reader;
ByteArrayOutputStream bos;
PdfStamper stamper;
try {
String fonts = System.getProperty("user.dir") + File.separator + "fonts" + File.separator;
// 特别注意一下,linux路径只能使用/ window \ / 都可以
File file = new File(fonts);
if (!file.exists()) {
//TODO 这里可以再次进行字体文件上传的校验,当发现没有上传成功后的补救
}
String path1 = fonts + songFonts + ",0";
// 设置 css中 的字体样式(暂时仅支持宋体和黑体) 必须,不然中文不显示
BaseFont bf = BaseFont.createFont(path1, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
// // 此处的字体,服务要是在linux上,中文会出现导出填不上的情况,所以,此处字体必填
// BaseFont bf = BaseFont.createFont("STSongStd-Light", "UniGB-UCS2-H", BaseFont.EMBEDDED);
Font FontChinese = new Font(bf, 5, Font.NORMAL);
// 读取pdf模板
reader = new PdfReader(templatePath);
// FileInputStream is = new FileInputStream(fileTemplate);
bos = new ByteArrayOutputStream();
stamper = new PdfStamper(reader, bos);
AcroFields form = stamper.getAcroFields();
java.util.Iterator<String> it = form.getFields().keySet().iterator();
form.addSubstitutionFont(bf);
while (it.hasNext()) {
String name = it.next();
System.out.println(name);
String value = o.get(name) != null ? o.get(name).toString() : null;
log.info("名字:{},标签:{}", value, name);
if ("qrImage".equals(name)) {
// byte[] image = o.get(name) != null ? (byte[]) o.get(name) : null;
// if (image == null) {
// insertImage(form, "qrImage", stamper, getImagesPath("lydx.png"));
// continue;
// }
if (value == null) {
continue;
}
insertImageV2(form, "qrImage", stamper, value);
} else {
form.setField(name, value);
}
}
// 如果为false那么生成的PDF文件还能编辑,一定要设为true
stamper.setFormFlattening(true);
stamper.close();
log.info("插入成功");
Document doc = new Document();
Font font = new Font(bf, 32);
PdfCopy copy = new PdfCopy(doc, os);
doc.open();
PdfImportedPage importPage = copy.getImportedPage(new PdfReader(bos.toByteArray()), 1);
copy.addPage(importPage);
doc.close();
} catch (IOException | DocumentException e) {
log.error("利用模板导出PDF失败:{}", e);
}
}
public String getPdfTempPath(String fileName) throws URISyntaxException {
return Objects.requireNonNull(MyPdfUtils.class.getClassLoader().getResource("templates" + File.separator + "pdfTemp" + File.separator + fileName)).toURI().toString();
}
public String getImagesPath(String fileName) throws URISyntaxException {
return Objects.requireNonNull(MyPdfUtils.class.getClassLoader().getResource("templates" + File.separator + "images" + File.separator + fileName)).toURI().toString();
}
public static byte[] getByteByUrl(String fileUrl) {
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
InputStream inputStream = null;
byte[] result = null;
try {
URL imageUrl = new URL(fileUrl);
HttpURLConnection conn = (HttpURLConnection) imageUrl.openConnection();
conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
inputStream = conn.getInputStream();
byte[] buffer = new byte[1024];
int len = 0;
while ((len = inputStream.read(buffer)) != -1) {
outStream.write(buffer, 0, len);
}
result = outStream.toByteArray();
return result;
} catch (Exception ignored) {
} finally {
try {
if (inputStream != null) {
inputStream.close();
}
outStream.close();
} catch (Exception ignored) {
}
}
return null;
}
public void insertImage(AcroFields form, String name, PdfStamper pdfStamper, byte[] url) throws DocumentException, IOException {
/**
* 添加图片
*/
int page = form.getFieldPositions(name).get(0).page;
Rectangle signReact = form.getFieldPositions(name).get(0).position;
float x = signReact.getLeft();
float y = signReact.getBottom();
Image image = Image.getInstance(url);
PdfContentByte under = pdfStamper.getOverContent(page);
image.scaleToFit(signReact.getWidth(), signReact.getHeight());
image.setAbsolutePosition(x, y);
under.addImage(image);
}
public void insertImage(AcroFields form, String name, PdfStamper pdfStamper, String url) throws DocumentException, IOException {
/**
* 添加图片
*/
int page = form.getFieldPositions(name).get(0).page;
Rectangle signReact = form.getFieldPositions(name).get(0).position;
float x = signReact.getLeft();
float y = signReact.getBottom();
Image image = Image.getInstance(url);
PdfContentByte under = pdfStamper.getOverContent(page);
image.scaleToFit(signReact.getWidth(), signReact.getHeight());
image.setAbsolutePosition(x, y);
under.addImage(image);
}
// public void insertImageV2(AcroFields form, String name, PdfStamper pdfStamper, String qrCodeBase64)
// throws DocumentException, IOException {
// // 获取字段的位置信息
// int page = form.getFieldPositions(name).get(0).page;
// Rectangle signRect = form.getFieldPositions(name).get(0).position;
// float x = signRect.getLeft();
// float y = signRect.getBottom();
// // 解析Base64图片数据
// String base64Data = qrCodeBase64;
// if (base64Data.startsWith("data:image/")) {
// // 去掉Base64前缀(如 data:image/png;base64,iVBORw0KG...)
// base64Data = base64Data.split(",")[1];
// }
// byte[] imageBytes = Base64.getDecoder().decode(base64Data);
// Image image = Image.getInstance(imageBytes);
// // 调整图片大小和位置
// image.scaleToFit(signRect.getWidth(), signRect.getHeight());
// image.setAbsolutePosition(x, y);
//
// // 插入图片
// PdfContentByte under = pdfStamper.getOverContent(page);
// under.addImage(image);
// }
public void insertImageV2(AcroFields form, String name, PdfStamper pdfStamper, String qrCodeBase64)
throws DocumentException, IOException {
// 获取字段的位置信息
int page = form.getFieldPositions(name).get(0).page;
Rectangle signRect = form.getFieldPositions(name).get(0).position;
float x = signRect.getLeft();
float y = signRect.getBottom();
// 解析Base64图片数据
String base64Data = qrCodeBase64.startsWith("data:image/") ? qrCodeBase64.split(",")[1] : qrCodeBase64;
byte[] imageBytes = Base64.getDecoder().decode(base64Data);
// 调试:临时保存图片到本地以验证Base64解码是否正确
// File tempFile = new File("debug_qrcode.png");
// try (FileOutputStream fos = new FileOutputStream(tempFile)) {
// fos.write(imageBytes);
// }
// 加载图片
Image image = Image.getInstance(imageBytes);
// 打印图片原始尺寸用于调试
System.out.println("Original width: " + image.getWidth() + ", height: " + image.getHeight());
// 调整图片大小和位置
image.scaleToFit(signRect.getWidth(), signRect.getHeight());
image.setAbsolutePosition(x, y);
// 插入图片
PdfContentByte canvas = pdfStamper.getOverContent(page); // 确保使用的是getOverContent
canvas.addImage(image);
// 可选:为了确保图片显示正常,可以尝试直接设置图片大小而非scaleToFit
// image.scaleAbsolute(signRect.getWidth(), signRect.getHeight());
}
public void forwardToBrowser(String contentType, String fileName, HttpServletResponse response) {
response.setContentType(contentType);
// 告诉浏览器,当前响应数据要求用户干预保存到文件中,以及文件名是什么 如果文件名有中文,必须URL编码
response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
}
public String addSuffix(Object t, String suffix) {
if (Objects.isNull(t)) {
return null;
}
return t + suffix;
}
public String getQrCodeBase64(String qrData) throws IOException, WriterException {
// 生成二维码
BufferedImage qrImage = generateQRCodeImage(qrData);
// 将二维码图像转换为Base64字符串
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(qrImage, "png", baos);
String qrImageBase64 = "data:image/png;base64," + javax.xml.bind.DatatypeConverter.printBase64Binary(baos.toByteArray());
// return Base64Util.encode(baos.toByteArray());
return qrImageBase64;
}
private BufferedImage generateQRCodeImage(String text) throws WriterException {
QRCodeWriter barcodeWriter = new QRCodeWriter();
BitMatrix bitMatrix = barcodeWriter.encode(text, BarcodeFormat.QR_CODE, 200, 200, getMinimalHints());
int width = bitMatrix.getWidth();
int height = bitMatrix.getHeight();
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
image.setRGB(x, y, bitMatrix.get(x, y) ? BLACK : WHITE);
}
}
return MatrixToImageWriter.toBufferedImage(bitMatrix);
}
/**
* 使用尽可能少的配置来生成二维码,可能不包括安静区
*/
private Map<EncodeHintType, Object> getMinimalHints() {
HashMap<EncodeHintType, Object> hints = new HashMap<>();
// 设置边缘为0,尝试去除留白
hints.put(EncodeHintType.MARGIN, 0);
// 可选:设置错误校正等级
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L);
return hints;
}
}


posted on 2026-04-14 12:12 HeavenTang 阅读(8) 评论(0) 收藏 举报
浙公网安备 33010602011771号