调离岗位

ln_ry20250512
20918 1 week ago
parent 63d68cb4c6
commit 441ba06176

@ -0,0 +1,60 @@
package com.ruoyi.web.controller.pdf.controller;
import com.ruoyi.web.controller.pdf.service.ChangePdfService;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.io.ByteArrayOutputStream;
import java.util.HashMap;
import java.util.Map;
@RestController
@RequestMapping("/api/ChangePdf")
public class ChangePdfController {
private final ChangePdfService ChangePdfService;
public ChangePdfController(ChangePdfService changePdfService) {
this.ChangePdfService = changePdfService;
}
@PostMapping(value = "/ChangeFill", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public ResponseEntity<byte[]> fillPdfForm(
@RequestParam(required = false) String name,
@RequestParam(required = false) String sex,
@RequestParam(required = false) String phone,
@RequestParam(required = false) String smPost,
@RequestParam(required = false) String smGrade,
@RequestParam(required = false) MultipartFile photo) throws Exception {
// 构建表单数据
Map<String, String> formData = new HashMap<>();
if (name != null) formData.put("姓名", name);
if (sex != null) formData.put("性别", sex);
if (phone != null) formData.put("联系电话", phone);
if (smPost != null) formData.put("涉密岗位", smPost);
if (smPost != null) formData.put("原涉密等级", smGrade);
// 构建图片数据
Map<String, MultipartFile> imageData = new HashMap<>();
if (photo != null && !photo.isEmpty()) {
imageData.put("照片", photo);
}
// 生成PDF
ByteArrayOutputStream outputStream = ChangePdfService.fillForm(formData, imageData);
// 返回PDF文件
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_PDF);
headers.setContentDispositionFormData("attachment", "output.pdf");
return ResponseEntity.ok()
.headers(headers)
.body(outputStream.toByteArray());
}
}

@ -0,0 +1,199 @@
package com.ruoyi.web.controller.pdf.service;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.font.PDType0Font;
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm;
import org.apache.pdfbox.pdmodel.interactive.form.PDField;
import org.apache.pdfbox.pdmodel.interactive.form.PDTextField;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.Map;
@Service
public class ChangePdfService {
// 定义最大和最小字体大小,用于动态调整
private static final float MAX_FONT_SIZE = 14;
private static final float MIN_FONT_SIZE = 8;
// 预估的字段宽度根据实际PDF调整
private static final float ESTIMATED_FIELD_WIDTH = 100f;
// 需要特殊处理的字段列表
private static final String[] AUTO_WRAP_FIELDS = {
"姓名","性别","联系电话","原涉密岗位名称"
};
public ByteArrayOutputStream fillForm(Map<String, String> formData,
Map<String, MultipartFile> imageData) throws IOException {
// 禁用系统字体扫描,只使用自定义字体
System.setProperty("org.apache.pdfbox.rendering.UseSystemFonts", "false");
// 提高字体解析警告的日志级别
System.setProperty("org.apache.commons.logging.Log", "org.apache.commons.logging.impl.SimpleLog");
System.setProperty("org.apache.commons.logging.simplelog.log.org.apache.fontbox", "ERROR");
PDDocument document = null;
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
try {
// 加载模板PDF
ClassLoader classLoader = getClass().getClassLoader();
File templateFile = new File(classLoader.getResource("static/file/pdf/smrydlgwspb.pdf").getFile());
document = PDDocument.load(templateFile);
PDAcroForm acroForm = document.getDocumentCatalog().getAcroForm();
if (acroForm == null) {
throw new IOException("PDF不包含表单域");
}
// 加载中文字体
PDType0Font font = PDType0Font.load(document,
new File(classLoader.getResource("static/file/pdf/STSONG.TTF").getFile()));
// 设置需要更新表单外观
acroForm.setNeedAppearances(true);
// 填充文本表单
for (Map.Entry<String, String> entry : formData.entrySet()) {
String fieldName = entry.getKey();
String fieldValue = entry.getValue();
PDField field = acroForm.getField(fieldName);
if (field != null) {
// 设置表单域为不可编辑
field.setReadOnly(true);
// 设置表单域不高亮显示
// for (PDAnnotationWidget widget : field.getWidgets()) {
// widget.setHighlightMode(PDAnnotationWidget.HIGHLIGHT_MODE_NONE);
// }
if (fieldValue != null && !fieldValue.isEmpty()) {
field.setValue(fieldValue);
if (field instanceof PDTextField) {
PDTextField textField = (PDTextField) field;
if (isAutoWrapField(fieldName)) {
// 计算文本在最大字体下的宽度
float textWidth = calculateTextWidth(fieldValue, font, MAX_FONT_SIZE);
// 如果文本宽度超过预估字段宽度,启用自动换行并调整字体
if (textWidth > ESTIMATED_FIELD_WIDTH) {
textField.setMultiline(true);
float fontSize = calculateFontSize(fieldValue, font);
textField.setDefaultAppearance("/" + font.getName() + " " + fontSize + " Tf 0 g");
} else {
// 文本未超出,使用默认字体和不换行
textField.setMultiline(false);
textField.setDefaultAppearance("/" + font.getName() + " " + MAX_FONT_SIZE + " Tf 0 g");
}
} else {
textField.setDefaultAppearance("/" + font.getName() + " 12 Tf 0 g");
}
}
} else {
// 无内容时,也设置默认外观
if (field instanceof PDTextField) {
((PDTextField) field).setDefaultAppearance("/" + font.getName() + " 12 Tf 0 g");
}
}
}
}
// 插入图片
insertImages(document, acroForm, imageData);
// 保存到输出流
document.save(outputStream);
} catch (Exception e) {
e.printStackTrace(); // 打印异常信息,方便调试
throw new IOException("处理PDF时出错", e);
} finally {
if (document != null) {
document.close();
}
}
return outputStream;
}
private void insertImages(PDDocument document, PDAcroForm acroForm,
Map<String, MultipartFile> imageData) throws IOException {
for (Map.Entry<String, MultipartFile> entry : imageData.entrySet()) {
String fieldName = entry.getKey();
MultipartFile file = entry.getValue();
PDField refField = acroForm.getField(fieldName);
// 设置表单域为不可编辑
if (refField != null) {
refField.setReadOnly(true);
}
if (refField != null && !file.isEmpty()) {
// 假设图片插入到第一页,你可以根据实际情况修改
PDPage page = document.getPage(0);
// 手动指定图片插入位置
float x = 440; // 可以根据实际情况调整
float y = 650; // 可以根据实际情况调整
PDImageXObject image = null;
PDPageContentStream contentStream = null;
try {
// 从上传的文件创建图片对象
image = PDImageXObject.createFromByteArray(document, file.getBytes(), file.getOriginalFilename());
// 计算图片尺寸(按比例缩放)
float imageWidth = image.getWidth();
float imageHeight = image.getHeight();
float maxWidth = 100;
float maxHeight = 100;
float scale = Math.min(maxWidth / imageWidth, maxHeight / imageHeight);
imageWidth *= scale;
imageHeight *= scale;
// 在指定位置绘制图片
contentStream = new PDPageContentStream(
document, page, PDPageContentStream.AppendMode.APPEND, true);
contentStream.drawImage(image, x, y, imageWidth, imageHeight);
} finally {
if (contentStream != null) {
contentStream.close();
}
}
}
}
}
// 判断是否是需要自动换行的字段
private boolean isAutoWrapField(String fieldName) {
for (String autoWrapField : AUTO_WRAP_FIELDS) {
if (autoWrapField.equals(fieldName)) {
return true;
}
}
return false;
}
// 计算文本在指定字体和大小下的宽度
private float calculateTextWidth(String text, PDType0Font font, float fontSize) throws IOException {
if (text == null || text.isEmpty()) {
return 0;
}
// 计算文本宽度,考虑字符间距
return font.getStringWidth(text) / 1000 * fontSize;
}
// 计算适应字段的字体大小
private float calculateFontSize(String fieldValue, PDType0Font font) throws IOException {
float fontSize = MAX_FONT_SIZE;
float textWidth = calculateTextWidth(fieldValue, font, fontSize);
// 循环降低字体大小直到文本适合预估宽度
while (textWidth > ESTIMATED_FIELD_WIDTH && fontSize > MIN_FONT_SIZE) {
fontSize -= 0.5f;
textWidth = calculateTextWidth(fieldValue, font, fontSize);
}
return fontSize;
}
}
Loading…
Cancel
Save