diff --git a/ruoyi-admin/pom.xml b/ruoyi-admin/pom.xml
index 03a023d..aad287b 100644
--- a/ruoyi-admin/pom.xml
+++ b/ruoyi-admin/pom.xml
@@ -16,6 +16,41 @@
+
+ org.jsoup
+ jsoup
+ 1.14.3
+
+
+
+
+ org.apache.httpcomponents
+ httpcore
+ 4.4.13
+
+
+ org.springframework
+ spring-test
+ 5.2.15.RELEASE
+
+
+
+
+ com.itextpdf
+ itext-asian
+ 5.2.0
+
+
+
+ com.itextpdf
+ itextpdf
+ 5.5.13
+
+
+ com.itextpdf.tool
+ xmlworker
+ 5.5.13
+
org.projectlombok
lombok
@@ -68,6 +103,11 @@
knife4j-openapi2-spring-boot-starter
4.4.0
+
+ com.itextpdf
+ html2pdf
+ 1.17.2
+
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/gysl/controller/DpclglController.java b/ruoyi-admin/src/main/java/com/ruoyi/gysl/controller/DpclglController.java
index 392f0f4..a616b05 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/gysl/controller/DpclglController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/gysl/controller/DpclglController.java
@@ -7,10 +7,14 @@ import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.gysl.entity.Dpclgl;
import com.ruoyi.gysl.entity.request.DpclglPageReq;
import com.ruoyi.gysl.service.DpclglService;
+import com.ruoyi.gysl.utils.HtmlToPdfConverter;
+import com.ruoyi.gysl.utils.PdfUtils;
+import com.ruoyi.web.controller.common.CommonController;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.io.Serializable;
@@ -22,11 +26,15 @@ import java.util.List;
* @author makejava
* @since 2025-03-22 11:11:55
*/
-@Api(tags ="单片材料管理" )
+@Api(tags = "单片材料管理")
@RestController
@RequestMapping("/gysl/dpclgl")
-@PreAuthorize("@ss.hasAnyRoles('admin,common')")
+//@PreAuthorize("@ss.hasAnyRoles('admin,common')")
public class DpclglController extends BaseController {
+
+
+ @Resource
+ private CommonController commonController;
/**
* 服务对象
*/
@@ -36,7 +44,7 @@ public class DpclglController extends BaseController {
/**
* 分页查询所有数据
*
- * @param page 分页对象
+ * @param page 分页对象
* @param dpclgl 查询实体
* @return 所有数据
*/
@@ -93,5 +101,25 @@ public class DpclglController extends BaseController {
public AjaxResult delete(@RequestParam("idList") List idList) {
return success(dpclglService.removeByIds(idList));
}
+
+
+ /**
+ * 富文本导出
+ *
+ * @return 新增结果
+ */
+ @ApiOperation(value = "副编辑器内容生成pdf文件url")
+ @GetMapping("/unloadPdf")
+ public AjaxResult unloadPdf(@RequestParam(defaultValue = "文章标题") String htmlArticleTitle, @RequestParam(defaultValue = "文章内容") String htmlContent) {
+ try {
+ MultipartFile multipartFile = HtmlToPdfConverter.convertHtmlToPdf(htmlArticleTitle, htmlContent);
+ commonController.uploadFile(multipartFile);
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return AjaxResult.success();
+ }
+
}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/gysl/utils/HtmlToPdfConverter.java b/ruoyi-admin/src/main/java/com/ruoyi/gysl/utils/HtmlToPdfConverter.java
new file mode 100644
index 0000000..5245359
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/gysl/utils/HtmlToPdfConverter.java
@@ -0,0 +1,211 @@
+package com.ruoyi.gysl.utils;
+
+import com.itextpdf.text.Document;
+import com.itextpdf.text.DocumentException;
+import com.itextpdf.text.Image;
+import com.itextpdf.text.Paragraph;
+import com.itextpdf.text.pdf.PdfWriter;
+import com.itextpdf.tool.xml.XMLWorkerFontProvider;
+import com.itextpdf.tool.xml.XMLWorkerHelper;
+import org.jsoup.Jsoup;
+import org.jsoup.nodes.Element;
+import org.jsoup.select.Elements;
+import org.springframework.mock.web.MockMultipartFile;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.*;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Base64;
+import java.util.Date;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class HtmlToPdfConverter {
+
+ public static MultipartFile convertHtmlToPdf(String htmlArticleTitle, String htmlContent) throws IOException {
+
+ String ht = content2Html(htmlContent);
+
+
+ String path = System.getProperty("user.dir");
+ // 根据日期建文件夹
+ String format = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
+ String[] split = format.split("-");
+ Path dirPath = Paths.get(path, "temporary", split[0], split[1], split[2]);
+ try {
+ Files.createDirectories(dirPath);
+ } catch (IOException e) {
+ throw new RuntimeException("创建文件夹失败: " + e.getMessage(), e);
+ }
+ File pdfFile = new File(dirPath.toFile(), "pdf-" + System.currentTimeMillis() + ".pdf");
+ // 创建PDF文档
+ Document document = new Document();
+
+ FileOutputStream fos = null;
+ InputStream is = null;
+ try {
+ fos = new FileOutputStream(pdfFile);
+
+ PdfWriter writer = PdfWriter.getInstance(document, fos);
+ XMLWorkerFontProvider fontProvider = new XMLWorkerFontProvider(XMLWorkerFontProvider.DONTLOOKFORFONTS);
+ fontProvider.register("C:/Windows/Fonts/simsun.ttc");
+
+ document.open();
+ // 添加标题
+ Paragraph paragraph = new Paragraph(htmlArticleTitle); // 设置你自定义的字体格式
+ document.add(paragraph);
+ String updatedHtmlContent = "";
+ if (htmlContent.contains("img")) {
+ updatedHtmlContent = replaceImgSrcWithBase64(ht);
+
+ if (updatedHtmlContent != null) {
+ is = new ByteArrayInputStream(updatedHtmlContent.getBytes(StandardCharsets.UTF_8));
+ XMLWorkerHelper.getInstance().parseXHtml(writer, document, is, StandardCharsets.UTF_8, fontProvider);
+ // 添加图片
+ Elements imgElements = Jsoup.parse(updatedHtmlContent).select("img");
+ for (Element img : imgElements) {
+ String imgSrc = img.attr("src");
+ if (imgSrc.startsWith("data:image/jpeg;base64,")) {
+ String base64Data = imgSrc.substring("data:image/jpeg;base64,".length());
+ byte[] imageBytes = Base64.getDecoder().decode(base64Data);
+ Image image = Image.getInstance(imageBytes);
+ document.add(image); // 添加图片到 PDF
+ }
+ }
+ }
+
+ } else {
+ is = new ByteArrayInputStream(ht.getBytes(StandardCharsets.UTF_8));
+ XMLWorkerHelper.getInstance().parseXHtml(writer, document, is, StandardCharsets.UTF_8, fontProvider);
+
+ }
+
+ } catch (DocumentException | IOException e) {
+ throw new RuntimeException("转换PDF失败: " + e.getMessage(), e);
+ } finally {
+
+ if (document.isOpen()) {
+ document.close(); // 确保Document关闭
+ }
+ if (fos != null) {
+ try {
+ fos.close(); // 关闭文件输出流
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ if (is != null) {
+ try {
+ is.close(); // 关闭输入流
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ return getMultipartFile(pdfFile);
+ }
+
+ private static MultipartFile getMultipartFile(File file) throws IOException {
+ try (FileInputStream fileInputStream = new FileInputStream(file)) {
+ return new MockMultipartFile(file.getName(), file.getName(), "application/pdf", fileInputStream);
+ }
+ }
+
+ public static String content2Html(String htmlContent) {
+ String COMPLETE_CONTENT = "" + htmlContent + "";
+ return COMPLETE_CONTENT.replace("
", "
");
+ }
+
+
+ private static String replaceImgSrcWithBase64(String htmlContent) {
+ List imgSrcs = new ArrayList<>();
+ String regex = "
]+src=\"([^\"]+)\"[^>]*>"; // 正确的正则表达式
+ Pattern pattern = Pattern.compile(regex);
+ Matcher matcher = pattern.matcher(htmlContent);
+ String baseUrl = "http://39.101.188.84:7071";
+
+ // 使用 StringBuilder 来构建新的 HTML
+ StringBuilder updatedHtml = new StringBuilder(htmlContent);
+
+ // 定义要替换的起始位置
+ int offset = 0;
+
+ while (matcher.find()) {
+ String imgSrc = matcher.group(1); // 捕获组返回 img src 的值
+ String imgUrl = baseUrl + imgSrc;
+
+ // 将 URL 转化为 Base64
+ try {
+ URL url = new URL(imgUrl);
+ HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+ connection.setRequestProperty("User-Agent", "Mozilla/5.0"); // 添加 User-Agent
+ connection.setDoInput(true);
+ connection.connect();
+ InputStream inputStream = connection.getInputStream();
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ byte[] buffer = new byte[1024];
+ int bytesRead;
+ while ((bytesRead = inputStream.read(buffer)) != -1) {
+ outputStream.write(buffer, 0, bytesRead);
+ }
+ inputStream.close();
+ byte[] imageBytes = outputStream.toByteArray();
+ String base64 = Base64.getEncoder().encodeToString(imageBytes);
+
+ // 替换 img 标签的 src 属性为 Base64 数据
+ String base64ImgTag = "
";
+ int start = matcher.start() + offset; // 累计偏移量
+ int end = matcher.end();
+
+ // 替换原来的 img 标签
+ updatedHtml.replace(start, end, base64ImgTag);
+ //System.out.println(updatedHtml.toString());
+ // 更新偏移量
+ offset += base64ImgTag.length() - (end - start);
+ } catch (Exception e) {
+ e.printStackTrace();
+ return null; // 处理异常或返回特定的错误值
+ }
+ }
+ return updatedHtml.toString();
+ }
+
+ public String convertImageToBase64(String imgUrl) {
+ try {
+ // String encodedImgUrl = URLEncoder.encode(imgUrl, StandardCharsets.UTF_8.toString());
+
+ URL url = new URL(imgUrl);
+ HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+ connection.setRequestProperty("User-Agent", "Mozilla/5.0"); // 添加 User-Agent
+ connection.setDoInput(true);
+ connection.connect();
+ InputStream inputStream = connection.getInputStream();
+
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ byte[] buffer = new byte[1024];
+ int bytesRead;
+ while ((bytesRead = inputStream.read(buffer)) != -1) {
+ outputStream.write(buffer, 0, bytesRead);
+ }
+ inputStream.close();
+
+ byte[] imageBytes = outputStream.toByteArray();
+ String base64 = Base64.getEncoder().encodeToString(imageBytes);
+ return "data:image/jpeg;base64," + base64; // 根据实际情况修改 MIME 类型
+ } catch (Exception e) {
+ e.printStackTrace();
+ return null; // 处理异常或返回特定的错误值
+ }
+ }
+
+
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/gysl/utils/ImgBase64Extractor.java b/ruoyi-admin/src/main/java/com/ruoyi/gysl/utils/ImgBase64Extractor.java
new file mode 100644
index 0000000..3538f36
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/gysl/utils/ImgBase64Extractor.java
@@ -0,0 +1,55 @@
+package com.ruoyi.gysl.utils;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.ArrayList;
+import java.util.Base64;
+import java.util.List;
+
+public class ImgBase64Extractor {
+
+ public static void main(String[] args) throws IOException {
+ String imgUrl ="http://39.101.188.84:7071/profile/upload/2025/03/24/abc_20250324154129A006.jpg";
+
+ URL url = new URL(imgUrl);
+ HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+ connection.setRequestMethod("GET");
+ connection.setDoInput(true);
+ // 添加请求头
+ connection.setRequestProperty("User-Agent", "Mozilla/5.0");
+ connection.setRequestProperty("Accept", "image/webp,image/apng,image/*,*/*;q=0.8");
+ connection.setRequestProperty("Accept-Language", "en-US,en;q=0.5");
+
+ // 连接并获取响应
+ connection.connect();
+
+ // 检查响应码
+ int responseCode = connection.getResponseCode();
+ if (responseCode == HttpURLConnection.HTTP_OK) {
+ // 连接成功,获取输入流
+ InputStream inputStream = connection.getInputStream();
+
+ // 读取输入流
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ byte[] buffer = new byte[1024];
+ int bytesRead;
+
+ while ((bytesRead = inputStream.read(buffer)) != -1) {
+ outputStream.write(buffer, 0, bytesRead);
+ }
+
+ inputStream.close();
+ byte[] imageBytes = outputStream.toByteArray();
+ System.out.println(imageBytes);
+ } else {
+ System.out.println("Error: Server returned HTTP response code: " + responseCode);
+
+ }
+ }
+
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/gysl/utils/PdfUtils.java b/ruoyi-admin/src/main/java/com/ruoyi/gysl/utils/PdfUtils.java
new file mode 100644
index 0000000..ce2589b
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/gysl/utils/PdfUtils.java
@@ -0,0 +1,168 @@
+package com.ruoyi.gysl.utils;
+
+
+
+import com.itextpdf.text.Document;
+import com.itextpdf.text.DocumentException;
+import com.itextpdf.text.Font;
+import com.itextpdf.text.Paragraph;
+import com.itextpdf.text.pdf.BaseFont;
+import com.itextpdf.text.pdf.PdfWriter;
+import com.itextpdf.tool.xml.XMLWorkerFontProvider;
+import com.itextpdf.tool.xml.XMLWorkerHelper;
+import org.springframework.mock.web.MockMultipartFile;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.*;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+public class PdfUtils {
+
+
+ // 定义全局的字体静态变量
+ private static Font titlefont;
+ private static Font headfont;
+ private static Font keyfont;
+ private static Font textfont;
+ // 最大宽度
+ private static int maxWidth = 520;
+
+ // 静态代码块
+ static {
+ try {
+ // 不同字体(这里定义为同一种字体:包含不同字号、不同style)
+ BaseFont bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
+ titlefont = new Font(bfChinese, 16, Font.BOLD);
+ headfont = new Font(bfChinese, 14, Font.BOLD);
+ keyfont = new Font(bfChinese, 10, Font.BOLD);
+ textfont = new Font(bfChinese, 10, Font.NORMAL);
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * html转换成pdf文件
+ *
+ * @param htmlContent
+ * @throws Exception
+ */
+ public MultipartFile html2Pdf(String htmlArticleTitle, String htmlContent) throws Exception {
+ htmlContent = this.content2Html(htmlContent);
+
+ String path = System.getProperty("user.dir");
+
+ //根据日期建文件夹
+ Date date = new Date();
+ SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
+ String format = formatter.format(date);
+ String[] split = format.split("-");
+ File dir = new File(path + "/temporary");
+ if (!dir.exists()) {
+ dir.mkdir();
+ }
+ File dir2 = new File(path + "/temporary" + "/" + split[0]);
+ if (!dir2.exists()) {
+ dir2.mkdir();
+ }
+ File dir3 = new File(path + "/temporary" + "/" + split[0] + "/" + split[1]);
+ if (!dir3.exists()) {
+ dir3.mkdir();
+ }
+ File dir4 = new File(path + "/temporary" + "/" + split[0] + "/" + split[1] + "/" + split[2]);
+ if (!dir4.exists()) {
+ dir4.mkdir();
+ }
+ File pdfFile = new File(dir4 + "/pdf" + "-" + System.currentTimeMillis() + ".pdf");
+ //1 打开文件流
+ Document document = new Document();
+ FileOutputStream fos = new FileOutputStream(pdfFile);
+ System.out.println(pdfFile);
+ InputStream is = new ByteArrayInputStream(htmlContent.getBytes(StandardCharsets.UTF_8));
+ //InputStream cssIs = new ByteArrayInputStream(getCssFile());
+ PdfWriter writer = null;
+ try {
+ writer = PdfWriter.getInstance(document, fos);
+ //3. 设置字体
+ XMLWorkerFontProvider fontProvider1 = new XMLWorkerFontProvider(XMLWorkerFontProvider.DONTLOOKFORFONTS);
+ //fontProvider1.register(path+"\\simsun.ttc");//本地
+ fontProvider1.register(path + "/simsun.ttc");//部署服务器
+
+ //3 打开文档
+ document.open();
+ // 段落
+ Paragraph paragraph = new Paragraph(htmlArticleTitle, titlefont);
+ paragraph.setAlignment(1); //设置文字居中 0靠左 1,居中 2,靠右
+ paragraph.setIndentationLeft(12); //设置左缩进
+ paragraph.setIndentationRight(12); //设置右缩进
+ paragraph.setFirstLineIndent(24); //设置首行缩进
+ paragraph.setLeading(20f); //行间距
+ paragraph.setSpacingBefore(5f); //设置段落上空白
+ paragraph.setSpacingAfter(10f); //设置段落下空白
+ document.add(paragraph);
+ //4 html转为pdf
+ //XMLWorkerHelper.getInstance().parseXHtml(writer, document, is, cssIs, Charset.forName("UTF-8"), fontProvider1);
+ XMLWorkerHelper.getInstance().parseXHtml(writer, document, is, StandardCharsets.UTF_8, fontProvider1);
+
+ } catch (DocumentException | IOException e) {
+ throw new RuntimeException("转pdf失败罗~");
+ } finally {
+ if (null != writer) {
+ writer.flush();
+ }
+ //5 关闭文档
+ document.close();
+ fos.close();
+ //cssIs.close();
+ is.close();
+ writer.close();
+ MultipartFile multipartFile = getMulipartFiles2(pdfFile + "");
+ System.out.println("pdfFile = " + pdfFile);
+ return multipartFile;
+ }
+ }
+
+ public MultipartFile getMulipartFiles2(String filePath) throws IOException {
+ File file = new File(filePath);
+ FileInputStream fileInputStream = new FileInputStream(file);
+ MultipartFile multipartFile = new MockMultipartFile(file.getName(), file.getName(),
+ "application/sql", fileInputStream);
+ long size = multipartFile.getSize();
+ return multipartFile;
+ }
+
+
+ /**
+ * 获取html
+ *
+ * @return
+ */
+ public String content2Html(String htmlContent) {
+ String COMPLETE_CONTENT = "" + htmlContent + "";
+ String content = COMPLETE_CONTENT;
+ content = content.replace("
", "
");
+ return content;
+ }
+
+ /**
+ * 获取样式文件
+ *
+ * @return
+ * @throws Exception
+ */
+ protected byte[] getCssFile() throws Exception {
+ FileInputStream fileInputStream = new FileInputStream("D:\\editor.css");
+ ByteArrayOutputStream outStream = new ByteArrayOutputStream();
+ byte[] buffer = new byte[1204];
+ int len = 0;
+ while ((len = fileInputStream.read(buffer)) != -1) {
+ outStream.write(buffer, 0, len);
+ }
+ fileInputStream.close();
+ return outStream.toByteArray();
+ }
+}
\ No newline at end of file