parent
7a0e7e5b3d
commit
c9cd4699a3
@ -1,232 +0,0 @@
|
|||||||
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 com.ruoyi.common.utils.http.HttpUtils;
|
|
||||||
import org.jsoup.Jsoup;
|
|
||||||
import org.jsoup.nodes.Element;
|
|
||||||
import org.jsoup.select.Elements;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
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 {
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(HttpUtils.class);
|
|
||||||
|
|
||||||
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 {
|
|
||||||
// clearTemporaryDirectory(Paths.get(path, "temporary")); // 清理目录
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
MultipartFile multipartFile = getMultipartFile(pdfFile);
|
|
||||||
// 在此处删除创建的 PDF 文件
|
|
||||||
boolean deleted = pdfFile.delete();
|
|
||||||
if (!deleted) {
|
|
||||||
log.error("删除文件失败: " + pdfFile.getAbsolutePath());
|
|
||||||
|
|
||||||
}
|
|
||||||
return multipartFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
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 = "<html><head></head><body style=\"font-family: SimSun;\">" + htmlContent + "</body></html>";
|
|
||||||
return COMPLETE_CONTENT.replace("<br>", "<br/>");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private static String replaceImgSrcWithBase64(String htmlContent) {
|
|
||||||
List<String> imgSrcs = new ArrayList<>();
|
|
||||||
String regex = "<img[^>]+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 = "<img src=\"data:image/jpeg;base64," + base64 + "\" />";
|
|
||||||
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; // 处理异常或返回特定的错误值
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private static void clearTemporaryDirectory(Path directory) {
|
|
||||||
File dir = directory.toFile();
|
|
||||||
if (dir.exists() && dir.isDirectory()) {
|
|
||||||
for (File file : dir.listFiles()) {
|
|
||||||
if (!file.isDirectory()) {
|
|
||||||
file.delete(); // 删除文件
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,6 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
|
||||||
<mapper namespace="com.ruoyi.docking.mapper.ProjectMapper">
|
|
||||||
|
|
||||||
</mapper>
|
|
||||||
|
|
Loading…
Reference in new issue