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