Browse Source

2024-12-12

导出Word,并转PDF
java8
fengyuan_yang 1 year ago
parent
commit
2422d83af8
  1. 29
      pom.xml
  2. 32
      src/main/java/com/xujie/sys/modules/toWord/test1/Arrears.java
  3. 84
      src/main/java/com/xujie/sys/modules/toWord/test1/WordTest.java
  4. 35
      src/main/java/com/xujie/sys/modules/toWord/test2/controller/TestWordController.java
  5. 9
      src/main/java/com/xujie/sys/modules/toWord/test2/entity/WordEntity.java
  6. 11
      src/main/java/com/xujie/sys/modules/toWord/test2/service/TestWordService.java
  7. 75
      src/main/java/com/xujie/sys/modules/toWord/test2/service/impl/TestWordServiceImpl.java
  8. 178
      src/main/java/com/xujie/sys/modules/toWord/test2/utils/UpDownUtil.java
  9. 195
      src/main/java/com/xujie/sys/modules/toWord/test2/utils/WordPDFUtil.java
  10. 4
      src/main/resources/mapper/pms/QcReportMapper.xml

29
pom.xml

@ -112,6 +112,34 @@
<version>4.1.2</version>
</dependency>
<!-- word生成工具类 -->
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.31</version>
</dependency>
<!--pdf生成工具类-->
<dependency>
<groupId>org.xhtmlrenderer</groupId>
<artifactId>core-renderer</artifactId>
<version>R8</version>
</dependency>
<!--引入word转pdf jar包-->
<dependency>
<groupId>aspose</groupId>
<artifactId>words</artifactId>
<version>15.8.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/jar/aspose-words-16.8.0.jar</systemPath>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
@ -342,6 +370,7 @@
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<fork>true</fork>
<includeSystemScope>true</includeSystemScope>
</configuration>
</plugin>
<!-- 跳过单元测试 -->

32
src/main/java/com/xujie/sys/modules/toWord/test1/Arrears.java

@ -0,0 +1,32 @@
package com.xujie.sys.modules.toWord.test1;
public class Arrears{
private String name;
private Integer num;
private String endDay;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getNum() {
return num;
}
public void setNum(Integer num) {
this.num = num;
}
public String getEndDay() {
return endDay;
}
public void setEndDay(String endDay) {
this.endDay = endDay;
}
}

84
src/main/java/com/xujie/sys/modules/toWord/test1/WordTest.java

@ -0,0 +1,84 @@
package com.xujie.sys.modules.toWord.test1;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.springframework.web.bind.annotation.RestController;
import sun.misc.BASE64Encoder;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@RestController
public class WordTest {
public static void crateWord(Map<String, Object> dataMap, String templateDir, String templateName, String targetFile){
try (Writer writer = Files.newBufferedWriter(Paths.get(targetFile), StandardCharsets.UTF_8)) {
// 创建并配置FreeMarker配置对象
Configuration configuration = new Configuration(Configuration.VERSION_2_3_31);
configuration.setDefaultEncoding("UTF-8");
// 设置模板加载路径为文件系统上的绝对路径
configuration.setDirectoryForTemplateLoading(new File(templateDir));
// 加载模板
Template template = configuration.getTemplate(templateName);
// 渲染模板
template.process(dataMap, writer);
} catch (IOException | TemplateException e) {
throw new RuntimeException(e);
}
}
public static String getImageBase64Str(String imgFile) {
try( InputStream in = new FileInputStream(imgFile)) {
byte[] data = new byte[in.available()];
in.read(data);
BASE64Encoder encoder = new BASE64Encoder();
return encoder.encode(data);
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private static Map<String, Object> prepareParam(){
LocalDate currentDate = LocalDate.now();
List<Arrears> arrList = new ArrayList<>();
arrList.add(new Arrears(){{setName("白银");setNum(500);setEndDay("三月内");}});
arrList.add(new Arrears(){{setName("黄金");setNum(100);setEndDay("一年内");}});
arrList.add(new Arrears(){{setName("只因");setNum(50);setEndDay("两年半");}});
//填充所需要的数据
Map<String, Object> dataMap = new HashMap<>();
dataMap.put("person1", "杨奉源");
dataMap.put("money", "一个亿");
dataMap.put("year", String.valueOf(currentDate.getYear()));
dataMap.put("month", String.valueOf(currentDate.getMonthValue()));
dataMap.put("day", String.valueOf(currentDate.getDayOfMonth()));
dataMap.put("person2", "张海波");
dataMap.put("phoneNumber", "135xxxxxxxx");
dataMap.put("arrList", arrList);
dataMap.put("image1", getImageBase64Str("D:\\ckp-file\\只因你太美.jpeg"));
return dataMap;
}
public static void main(String[] args) throws IOException {
//准备参数
Map<String, Object> dataMap = prepareParam();
crateWord(dataMap,"/ckp-file/","欠条.ftl", "D:\\ckp-file\\qiantiao.doc");
System.out.println(6666666);
}
}

35
src/main/java/com/xujie/sys/modules/toWord/test2/controller/TestWordController.java

@ -0,0 +1,35 @@
package com.xujie.sys.modules.toWord.test2.controller;
import cn.hutool.core.io.FileUtil;
import com.xujie.sys.modules.toWord.test2.entity.WordEntity;
import com.xujie.sys.modules.toWord.test2.service.TestWordService;
import com.xujie.sys.modules.toWord.test2.utils.UpDownUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
@RestController
@RequestMapping("/testWord/test2")
public class TestWordController {
@Autowired
private TestWordService testWordService;
@PostMapping("/exportWordOrPdf")
public void exportWordOrPdf(@RequestBody WordEntity query, HttpServletResponse response) {
try {
File file = testWordService.exportWordOrPdfZIP(query, response);
UpDownUtil.download(file,response); // 将临时文件下载到浏览器
FileUtil.del(file); // 下载完之后将临时文件删除
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
}

9
src/main/java/com/xujie/sys/modules/toWord/test2/entity/WordEntity.java

@ -0,0 +1,9 @@
package com.xujie.sys.modules.toWord.test2.entity;
import lombok.Data;
@Data
public class WordEntity {
private String code;
private Boolean isPdf;
}

11
src/main/java/com/xujie/sys/modules/toWord/test2/service/TestWordService.java

@ -0,0 +1,11 @@
package com.xujie.sys.modules.toWord.test2.service;
import com.xujie.sys.modules.toWord.test2.entity.WordEntity;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
public interface TestWordService {
File exportWordOrPdfZIP(WordEntity query, HttpServletResponse response) throws IOException;
}

75
src/main/java/com/xujie/sys/modules/toWord/test2/service/impl/TestWordServiceImpl.java

@ -0,0 +1,75 @@
package com.xujie.sys.modules.toWord.test2.service.impl;
import cn.hutool.core.io.FileUtil;
import com.xujie.sys.modules.toWord.test1.Arrears;
import com.xujie.sys.modules.toWord.test2.entity.WordEntity;
import com.xujie.sys.modules.toWord.test2.service.TestWordService;
import com.xujie.sys.modules.toWord.test2.utils.UpDownUtil;
import com.xujie.sys.modules.toWord.test2.utils.WordPDFUtil;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Service
public class TestWordServiceImpl implements TestWordService {
public static final String templateName = "欠条.ftl";
public static final String templateDir = "/ckp-file/";
public static final String templatePath = "D:/ckp-file/templates/";
@Override
public File exportWordOrPdfZIP(WordEntity queryVo, HttpServletResponse response) throws IOException {
String code = queryVo.getCode();
boolean isPdf = queryVo.getIsPdf();
String filePath = "";
File file = new File(templatePath); // 获取临时的根路径
// 判断文件路径是否存在
if (!file.exists()) {
file.mkdirs();
}
System.out.println("保存的路径=========>>>>>>>" + file.getPath());
String wordName = file.getPath() + "/" + code + ".doc"; // 设置导出的word的全路径名称
exportFormatWord(queryVo, code + ".doc"); // 生成word
filePath = wordName;
if (isPdf) { //生成pdf
String pdfName = file.getPath() + "/" + code + ".pdf"; // 设置导出的pdf的全路径名称
WordPDFUtil.wordConvertPdf(wordName,pdfName); // 将word转成pdf
FileUtil.del(wordName); // 将word文件删除
filePath = pdfName;
}
return new File(filePath);
}
/**
* 生成word
*/
public void exportFormatWord(WordEntity query, String code){
LocalDate currentDate = LocalDate.now();
List<Arrears> arrList = new ArrayList<>();
arrList.add(new Arrears(){{setName("白银");setNum(500);setEndDay("三月内");}});
arrList.add(new Arrears(){{setName("黄金");setNum(100);setEndDay("一年内");}});
arrList.add(new Arrears(){{setName("只因");setNum(50);setEndDay("两年半");}});
//填充所需要的数据
Map<String, Object> dataMap = new HashMap<>();
dataMap.put("person1", "杨奉源");
dataMap.put("money", "一个亿");
dataMap.put("year", String.valueOf(currentDate.getYear()));
dataMap.put("month", String.valueOf(currentDate.getMonthValue()));
dataMap.put("day", String.valueOf(currentDate.getDayOfMonth()));
dataMap.put("person2", "张海波");
dataMap.put("phoneNumber", "135xxxxxxxx");
dataMap.put("arrList", arrList);
dataMap.put("image1", UpDownUtil.getImageBase64Str("D:\\ckp-file\\只因你太美.jpeg"));
dataMap.put("code",code); // 设置页眉
//生成word文件到临时文件夹下
WordPDFUtil.exportWord(dataMap, templateDir, templateName, templatePath + code);
}
}

178
src/main/java/com/xujie/sys/modules/toWord/test2/utils/UpDownUtil.java

@ -0,0 +1,178 @@
package com.xujie.sys.modules.toWord.test2.utils;
import cn.hutool.core.util.StrUtil;
import sun.misc.BASE64Encoder;
import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
/**
* 文件上传下载工具类
*/
public class UpDownUtil {
public static String getImageBase64Str(String imgFile) {
try( InputStream in = new FileInputStream(imgFile)) {
byte[] data = new byte[in.available()];
in.read(data);
BASE64Encoder encoder = new BASE64Encoder();
return encoder.encode(data);
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* 将图片内容转换成Base64编码的字符串
* @param path 图片文件的全路径名称
* @return base64字符串和图片宽高
*/
public static Map<String,String> getImageBase64String(String path) {
Map<String,String> map = new HashMap<>();
if (StrUtil.isEmpty(path)) return null;
File file = new File(path);
if (!file.exists()) return null;
InputStream is = null;
InputStream is1 = null;
byte[] data = null;
try {
is = new FileInputStream(file);
is1 = new FileInputStream(file);
data = new byte[is.available()];
is.read(data);
//获取图片宽高
BufferedImage image = ImageIO.read(is1);
//图片的原始宽高
map.put("height",Integer.toString(image.getHeight()));
map.put("width",Integer.toString(image.getWidth()));
is.close();
is1.close();
} catch (IOException e) {
e.printStackTrace();
}
BASE64Encoder encoder = new BASE64Encoder();
map.put("encode",encoder.encode(data));
return map;
}
/**
* 将图片内容转换成Base64编码的字符串并获得图片宽高进行缩放
* @param path 图片文件的全路径名称
* @param flag 判断图片是否是用户头像
* @return base64字符串和图片宽高
*/
public static Map<String,String> getImageBase64String(String path,boolean flag) {
Map<String,String> map = new HashMap<>();
if (StrUtil.isEmpty(path)) return null;
File file = new File(path);
if (!file.exists()) return null;
InputStream is = null;
InputStream is1 = null;
byte[] data = null;
try {
is = new FileInputStream(file);
is1 = new FileInputStream(file);
data = new byte[is.available()];
is.read(data);
//获取图片宽高
BufferedImage image = ImageIO.read(is1);
//图片的原始宽高
int height = image.getHeight();
int width = image.getWidth();
//如果图片是用户头像的话按照50*50的标准来判断是否要缩小否则的话按照500*500
if (flag){
//宽或高有一项大于50时等比缩小
if (width > 50 || height > 50){
int cWidth = 50;
int cHeight = 50;
int showWidth = cWidth;
int showHeight = cHeight;
//原图宽高太大进行等比缩放通过等比缩放解决图片变形的问题
if(1.0 * width/height >= 1.0 * cWidth/cHeight){
//图片比较宽
showHeight = showWidth * height / width;
}else {
//图片比较长
showWidth = showHeight * width / height;
}
map.put("height",Integer.toString(showHeight));
map.put("width",Integer.toString(showWidth));
}else {
//否则使用图片的原始大小
map.put("height",Integer.toString(height));
map.put("width",Integer.toString(width));
}
}else {
//宽或高大于500时进行缩放
if (width > 500 || height > 500){
int cWidth = 500;
int cHeight = 500;
int showWidth = cWidth;
int showHeight = cHeight;
//原图宽高太大进行等比缩放
if(1.0 * width/height >= 1.0 * cWidth/cHeight){
//图片比较宽
showHeight = showWidth * height / width;
}else {
//图片比较长
showWidth = showHeight * width / height;
}
map.put("height",Integer.toString(showHeight));
map.put("width",Integer.toString(showWidth));
}else {
map.put("height",Integer.toString(height));
map.put("width",Integer.toString(width));
}
}
is.close();
is1.close();
} catch (IOException e) {
e.printStackTrace();
}
BASE64Encoder encoder = new BASE64Encoder();
map.put("encode",encoder.encode(data));
return map;
}
public static void download(File file, HttpServletResponse response) throws IOException {
if (file == null || !file.exists()) {
throw new IllegalArgumentException("文件不存在");
}
//读取缓存1kb
byte[] buffer = new byte[1024];
FileInputStream fis;
BufferedInputStream bis;
response.setContentType("application/octet-stream");
response.setHeader("Content-disposition", "attachment; filename=" + new String(file.getName().getBytes("gbk"), "iso8859-1"));
try {
//读取文件
fis = new FileInputStream(file);
//加缓存
bis = new BufferedInputStream(fis);
//开始读取
int i = bis.read(buffer);
//设置输出流
ServletOutputStream os = response.getOutputStream();
//开始循环读取
while (i != -1) {
os.write(buffer, 0, i);
i = bis.read(buffer);
}
fis.close();
} catch (Exception e) {
throw new RuntimeException(e.getMessage());
}
}
}

195
src/main/java/com/xujie/sys/modules/toWord/test2/utils/WordPDFUtil.java

@ -0,0 +1,195 @@
package com.xujie.sys.modules.toWord.test2.utils;
import cn.hutool.system.OsInfo;
import cn.hutool.system.SystemUtil;
import com.aspose.words.Document;
import com.aspose.words.FontSettings;
import com.aspose.words.License;
import com.aspose.words.SaveFormat;
import com.lowagie.text.DocumentException;
import com.lowagie.text.Image;
import com.lowagie.text.pdf.*;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xhtmlrenderer.pdf.ITextFontResolver;
import org.xhtmlrenderer.pdf.ITextRenderer;
import java.io.*;
import java.net.MalformedURLException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Map;
/**
* wordpdf处理工具类
*/
public class WordPDFUtil {
protected static Logger logger = LoggerFactory.getLogger(WordPDFUtil.class);
/**
* 获取破解码文件内容
*/
public static boolean getLicense() throws IOException {
boolean result = false;
InputStream is = null;
try {
// license.xml应放在..\WebRoot\WEB-INF\classes路径下
is = WordPDFUtil.class.getClassLoader().getResourceAsStream("static/license.xml");
License license = new License();
license.setLicense(is);
result = true;
} catch (Exception e) {
e.printStackTrace();
} finally {
if (null != is) is.close();
}
return result;
}
/**
* 通过模板导出word格式文件
*
* @param dataMap 导出数据
* @param templateName 模板名称
* @param path 导出word的路径以及文件名称
*/
public static void exportWord(Map<String, Object> dataMap, String templateDir, String templateName, String path) {
try (Writer writer = Files.newBufferedWriter(Paths.get(path), StandardCharsets.UTF_8)) {
// 创建并配置FreeMarker配置对象
Configuration configuration = new Configuration(Configuration.VERSION_2_3_31);
configuration.setDefaultEncoding("UTF-8");
// 设置模板加载路径为文件系统上的绝对路径
configuration.setDirectoryForTemplateLoading(new File(templateDir));
// 加载模板
Template template = configuration.getTemplate(templateName);
// 渲染模板
template.process(dataMap, writer);
} catch (IOException | TemplateException e) {
throw new RuntimeException(e);
}
}
/**
* word转pdf文件
*
* @param Address 原文件地址
* @param pdfAddress 保存的pdf文件地址
*/
public static void wordConvertPdf(String Address, String pdfAddress) throws IOException {
// 验证License 若不验证则转化出的pdf文档会有水印产生
// if (!getLicense()) {
// return;
// }
FileOutputStream os = null;
//判断是否windows系统Linux要读取字体否则pdf字体为方格
OsInfo osInfo = SystemUtil.getOsInfo();
if (osInfo.isLinux()) {
String path = WordPDFUtil.class.getClassLoader().getResource("static/simsun.ttc").getPath();
FontSettings.getDefaultInstance().setFontsFolder(path, true);
}
try {
// 新建一个空白pdf文档
File file = new File(pdfAddress);
os = new FileOutputStream(file);
// Address是将要被转化的word文档
Document doc = new Document(Address);
// 全面支持DOC, DOCX, OOXML, RTF HTML, OpenDocument, PDF, EPUB, XPS, SWF 相互转换
doc.save(os, SaveFormat.PDF);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (null != os)
os.close();
}
}
/**
* @param htmlString html字符串
* @param path 生成pdf文件存储路径
* @param chineseFontPath 中文字体存储路径
*/
public static void htmlPDF(String htmlString, String path, String chineseFontPath) {
OutputStream os = null;
try {
os = new FileOutputStream(path);
ITextRenderer renderer = new ITextRenderer();
//html字符串转换模式
renderer.setDocumentFromString(htmlString);
// 解决中文不显示问题
ITextFontResolver fontResolver = renderer.getFontResolver();
fontResolver.addFont(chineseFontPath, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
renderer.layout();
renderer.createPDF(os);
} catch (MalformedURLException e) {
logger.warn(e.toString(), e);
} catch (FileNotFoundException e) {
logger.warn(e.toString(), e);
} catch (DocumentException e) {
logger.warn(e.toString(), e);
} catch (IOException e) {
logger.warn(e.toString(), e);
} finally {
if (os != null) {
try {
os.close();
} catch (IOException e) {
logger.warn(e.toString(), e);
}
}
}
}
/**
* pdf文件添加图片水印
*
* @param InPdfFile 要添加水印的pdf路径
* @param outPdfFile 添加水印完成的pdf输入路径
* @param markImagePath 添加图片水印的路径
* @param imgWidth 添加水印X坐标文件的四个角左下方的角坐标为0,0
* @param imgHeight 添加水印的Y坐标
*/
public static void addPDFLogo(String InPdfFile, String outPdfFile, String markImagePath, int imgWidth, int imgHeight) throws IOException, DocumentException {
System.out.println("========开始生成水印========>>>>>>" + InPdfFile);
PdfReader reader = new PdfReader(InPdfFile, "PDF".getBytes());
PdfStamper stamp = new PdfStamper(reader, new FileOutputStream(new File(outPdfFile)));
PdfContentByte under;
PdfGState gs1 = new PdfGState();
// 透明度设置
gs1.setFillOpacity(0.8f);
// 插入图片水印
Image img = Image.getInstance(markImagePath);
// 坐标
img.setAbsolutePosition(imgWidth, imgHeight);
// 旋转 弧度
img.setRotation(0);
// 旋转 角度
img.setRotationDegrees(0);
// 自定义大小
img.scaleAbsolute(595, 842);
//依照比例缩放
// img.scalePercent(50);
// 原pdf文件的总页数
int pageSize = reader.getNumberOfPages();
for (int i = 1; i <= pageSize; i++) {
// 水印在之前文本下
under = stamp.getUnderContent(i);
//水印在之前文本上
// under = stamp.getOverContent(i);
// 图片水印 透明度
under.setGState(gs1);
// 图片水印
under.addImage(img);
}
System.out.println("========完成水印生成========>>>>>>" + outPdfFile);
stamp.close();// 关闭
reader.close();
}
}

4
src/main/resources/mapper/pms/QcReportMapper.xml

@ -173,6 +173,10 @@
a.disposal_remark,
a.inspector_date,
a.inspector_no,
isnull(dbo.joint_id(a.site, a.bu_no, a.inspection_no, 'coordination'), '') as operator,
isnull(dbo.joint_name(a.site, a.bu_no, a.inspection_no, 'coordination'), '') as operatorName,
isnull(dbo.joint_id(a.site, a.bu_no, a.inspection_no, 'responsible'), '') as responsiblePerson,
isnull(dbo.joint_name2(a.site, a.bu_no, a.inspection_no, 'responsible'), '') as responsiblePersonName,
u.user_display as inspectorName,
a.seq_no,
a.batch_roll_no,

Loading…
Cancel
Save