依赖
<!--html转pdf工具 itext7 html2pdf -->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>html2pdf</artifactId>
<version>3.0.2</version>
</dependency>
<!-- only needed for Asian fonts -->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>font-asian</artifactId>
<version>7.1.13</version>
</dependency>
//todo str转jsonarray
List<ImagePathData> dataList = JSONUtil.toList(dto.getBase64Json(),ImagePathData.class);
// 根据 fileId 进行分组
Map<Long, List<ImagePathData>> groupedData = dataList.stream()
.collect(Collectors.groupingBy(ImagePathData::getFileId));
// 打印每个分组的数据
groupedData.forEach((fileId, group) -> {
InputStream inputStream = pdfUtilService.getPdfInputStream(group.get(0).getFileId());
for (ImagePathData imagePathData : group) {
inputStream = pdfUtilService.imageOverlayPdfStream(imagePathData.getBase64(),imagePathData.getPage(),imagePathData.getLeftX(),imagePathData.getBottomY(), imagePathData.getWidth(),imagePathData.getHeight(),inputStream);
}
});
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.json.JSONUtil;
import cn.tsit.whzb.admin.api.feign.RemoteFileService;
import cn.tsit.whzb.common.core.constant.SecurityConstants;
import cn.tsit.whzb.common.core.util.R;
import cn.tsit.whzb.server.util.ImagePathData;
import com.itextpdf.io.image.ImageData;
import com.itextpdf.io.image.ImageDataFactory;
import com.itextpdf.kernel.geom.PageSize;
import com.itextpdf.kernel.geom.Rectangle;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfReader;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.kernel.pdf.WriterProperties;
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
import com.itextpdf.kernel.pdf.xobject.PdfImageXObject;
import com.itextpdf.kernel.utils.PdfMerger;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.element.Image;
//import fr.opensagres.poi.xwpf.converter.pdf.PdfConverter;
//import fr.opensagres.poi.xwpf.converter.pdf.PdfOptions;
import io.swagger.v3.oas.models.security.SecurityScheme;
import org.apache.commons.compress.utils.Lists;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
//import org.ofdrw.converter.ConvertHelper;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Base64;
import java.util.Date;
import java.util.List;
@Service
public class PdfUtilService {
//单张插入
public InputStream merg(List<ImagePathData> imagePathList,Long fileId) throws IOException {
List<InputStream> sources = new ArrayList<>();
InputStream sourcepdf = getPdfInputStream(fileId);
InputStream sourcepdfA = getPdfInputStream(fileId);
List<InputStream> imagepdfs = null;
//todo 获取一个新的pdf
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
PdfWriter writer = new PdfWriter(outputStream, new WriterProperties().setFullCompressionMode(Boolean.TRUE));
PdfDocument pdfDocument = new PdfDocument(writer);
PdfMerger merger = new PdfMerger(pdfDocument);
//
imagePathList.forEach(imageData -> {
imageData.setImageStream(imageTopdf(imageData.getBase64()));
});
Integer last = 0;
List<ImagePathData> lists = getllll(imagePathList);
for (ImagePathData pathData : lists) {
if(!pathData.getOoo()){
PdfDocument imagepdf = new PdfDocument(new PdfReader(pathData.getImageStream()));
merger.merge(imagepdf,1,1);
imagepdf.close();
}else {
PdfDocument source = new PdfDocument(new PdfReader(sourcepdf));
merger.merge(source,pathData.getX(),pathData.getY());
source.close();
}
last = pathData.getPage();
}
PdfDocument source = new PdfDocument(new PdfReader(sourcepdfA));
if(last < source.getNumberOfPages()){
merger.merge(source,last+1,source.getNumberOfPages());
source.close();
}
merger.close();
return new ByteArrayInputStream(outputStream.toByteArray());
}
List<ImagePathData> getllll(List<ImagePathData> list){
List<ImagePathData> kk = new ArrayList<>();
Integer fornt = 0;
for (ImagePathData imagePathData : list) {
ImagePathData sssss = new ImagePathData();
if(imagePathData.getPage() == 1){
BeanUtil.copyProperties(imagePathData,sssss);
sssss.setOoo(false);
kk.add(sssss);
}else {
if(fornt+1 == imagePathData.getPage()){
BeanUtil.copyProperties(imagePathData,sssss);
sssss.setOoo(false);
kk.add(sssss);
}else {
ImagePathData aaa = new ImagePathData();
aaa.setOoo(true);
aaa.setX(fornt+1);
aaa.setY(imagePathData.getPage()-1);
kk.add(aaa);
BeanUtil.copyProperties(imagePathData,sssss);
sssss.setOoo(false);
kk.add(sssss);
}
}
fornt = imagePathData.getPage();
}
System.out.println(JSONUtil.toJsonPrettyStr(kk));
return kk;
}
/**
* imgesbase64转流
* @param imageBaseStr
* @return
*/
public InputStream imageTopdf(String imageBaseStr){
// 先处理图片 转为pdf
// 将Base64字符串转换为字节数组
byte[] imageBytes = Base64.getMimeDecoder().decode(imageBaseStr);
Image image = new Image(ImageDataFactory.create(imageBytes));
//创建 PdfWriter 对象,用于生成 PDF 文件
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
PdfWriter writer = new PdfWriter(outputStream, new WriterProperties().setFullCompressionMode(Boolean.TRUE));
PdfDocument pdfDocument = new PdfDocument(writer);
Document document = new Document(pdfDocument);
// 将图片添加到生成的 PDF 文件
document.add(image);
// 关闭生成的 PDF 文件
document.close();
// String FileNamePath = "D:\\file\\生成的.pdf";
// FileOutputStream fis = null;
// try {
// fis = new FileOutputStream(FileNamePath);
// } catch (FileNotFoundException e) {
// throw new RuntimeException(e);
// }
// try {
// fis.write(outputStream.toByteArray());
// } catch (IOException e) {
// throw new RuntimeException(e);
// }
return new ByteArrayInputStream(outputStream.toByteArray());
}
/**
* 文件路径转流
* @param pdfFilePath
* @return
* @throws IOException
*/
public InputStream convertPdfToStream(String pdfFilePath) throws IOException {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
try (FileInputStream fileInputStream = new FileInputStream(pdfFilePath)) {
byte[] buffer = new byte[1024];
int bytesRead;
// 从文件输入流读取数据并写入字节数组输出流
while ((bytesRead = fileInputStream.read(buffer)) != -1) {
byteArrayOutputStream.write(buffer, 0, bytesRead);
}
}
return new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
}
public static void main(String[] args) {
byte[] imageBytes = Base64.getMimeDecoder().decode("iVBORw0KGgoAAAANSUhEUgAAABYAAAAHCAYAAAAMPr0FAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAAEnQAABJ0Ad5mH3gAAADCSURBVChTXZFtEsMgCERz/0s1Y9IL9CNj2rNUykNQ2h87i6jPDVlkv4tpc+2PXy+hQ9ehKm19mqRQV/VX0inLAJZb94CZK3yAqRUE2BwY9SHNnPWpj6CawCTMcOuRiJr0HQLU0jrc3PqnqsNlezv4qpvx6SESAlxZs9+hAeehCQ0B7tIZ62UTDySoXcLpqSu8rdFXqKWe6z4a1UZiZhxJxw90WMig9HBPmzQe81F9LpyLGY8x4Bz0OqWdnpP/K0ZS5QuioSfuRx1FmwAAAABJRU5ErkJggg==");
ImageData image = ImageDataFactory.create(imageBytes);
System.out.println("image = " + image);
}
/**
*
* @param imageBaseStr 图片的base64
* @param page 第几页
* @param x 距左侧
* @param y 距底部
* @param width 图片宽度
* @param height 图片高度
* @param sourcepdf pdf源文件流
* @return
*/
public InputStream imageOverlayPdfStream(String imageBaseStr , Integer page, float x, float y,float width,float height, InputStream sourcepdf){
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
try {
byte[] imageBytes = Base64.getMimeDecoder().decode(imageBaseStr);
PdfReader pdfReader = new PdfReader(sourcepdf);
// 创建 PdfWriter 对象,用于写入新的 PDF 文件
// 获取一个新的pdf
PdfWriter pdfWriter = new PdfWriter(outputStream, new WriterProperties().setFullCompressionMode(Boolean.FALSE));
PdfDocument pdfDocument = new PdfDocument(pdfReader,pdfWriter);
// 创建 PdfCanvas 对象
PdfCanvas pdfCanvas = new PdfCanvas(pdfDocument.getPage(page));
ImageData image = ImageDataFactory.create(imageBytes);
PageSize pageSize = pdfDocument.getDefaultPageSize();
if(width == 0.0){
width = pageSize.getWidth();
}
if(height == 0.0){
height =pageSize.getHeight();
}
Rectangle rectangle = new Rectangle(x,y,width, height);
pdfCanvas.addImageFittedIntoRectangle(image, rectangle, false);
// pdfCanvas.addImage(image, rectangle, false); 还有其他的add方法
// 关闭文档
pdfDocument.close();
} catch (IOException e) {
e.printStackTrace();
}
return new ByteArrayInputStream(outputStream.toByteArray());
}
}
图片不清晰的问题解决
使用addImageFittedIntoRectangle()这个方法
将一张为pdf页大小n倍的png全透明图片,根据图片的宽高,会不失真的贴在pdf的页上,但是pdf页的大小会变得很大
这个是base64和测试过的pdf
这个图片为1944x2750的,但是会根据pdf的页面大小贴入,并且保证清晰度不变,还有其他的addImage**()方法,根据自己的需要切换


merg 方法是 操作pdf拆分合并的方法,我这里第一次尝试的是将图片转为pdf再直接替换合并进去,发现会有清晰度问题,随后改为了addImageFittedIntoRectangle()这个方法
1130

被折叠的 条评论
为什么被折叠?



