本文将提供多张图片(示例中为图片地址)导出到PDF,使用itextpdf包对导出进行处理;按照一页一图的方式进行填充到PDF,再进行下载导出;并设置图片在纸张的位置以及大小,可调整边距。
一、引入itextpdf依赖
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.4.2</version>
</dependency>
二、图片填充到PDF的处理代码
/**
* 将图片转换为PDF文件(传入多个图片文件集合,生成多页PDF)
* @author caiji
* @param pdfFileName pdf文件名
* @param fileUrl 图片地址
* @param paperType 纸张类型对象
* @return java.io.File
* @date 2022/2/22 14:49
*/
public static File generatePdfFile(String pdfFileName, List<String> fileUrl, Rectangle paperType) throws IOException, DocumentException {
Document doc = new Document(paperType);
PdfWriter.getInstance(doc, new FileOutputStream(pdfFileName));
doc.open();
for (String url : fileUrl) {
byte[] byteData = getFileByte(url);
Image image = Image.getInstance(byteData);
float height = image.getHeight();
float width = image.getWidth();
//获取同比压缩比例
int percent = getPercent(height, width,paperType);
//设置同比压缩
if(0 != percent) {
image.scalePercent(percent);
}
//设置左右居中
image.setAlignment(Image.MIDDLE);
//根据纸张高度和压缩后的高度计算 设置上边距,保持上下居中(未找到设置上下居中的方法)
//注意:如果是横向,要取pageSize.getWidth(),这里不会因为横向改变而改变高宽属性
float marginTop = (paperType.getHeight()-image.getScaledHeight())/2;
doc.setMargins(0,0,marginTop,0);
//新起一页,如果写在for的第一行,第一张不会生效
doc.newPage();
doc.add(image);
}
doc.close();
File pdfFile = new File(pdfFileName);
return pdfFile;
}
/**
*
* 用于下载PDF文件
*
* @param pdfFile PDF文件
* @param response HttpServletResponse
* @throws IOException IO异常
*/
public static void downloadPdfFile(File pdfFile, HttpServletResponse response) throws IOException {
FileInputStream fis = new FileInputStream(pdfFile);
byte[] bytes = new byte[fis.available()];
fis.read(bytes);
fis.close();
response.reset();
response.setHeader("Content-Type", "application/pdf");
response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(pdfFile.getName(), "UTF-8"));
OutputStream out = response.getOutputStream();
out.write(bytes);
out.flush();
out.close();
}
/**
* 等比压缩,获取压缩百分比
*
* @param height 图片的高度
* @param width 图片的宽度
* @param paperType 纸张类型对象
* @return 压缩百分比
*/
private static int getPercent(float height, float width, Rectangle paperType) {
float percent = 0.0F;
//获取纸张与图片的高、宽比例;这里减30是周边15,打印后周边距离约为10毫米即1厘米
float percentHeight = (paperType.getHeight()-30) / height * 100;
float percentWidth = (paperType.getWidth()-30) / width * 100;
//如果图片高或宽存在超出(此处比较高宽也要跟纸张减去30比,不然上面的留缝隙就没意义)
// 取高宽比较小的比例,避免压缩后存在另一边还需要压缩
if(height>(paperType.getHeight()-30) || width>(paperType.getWidth()-30)) {
percent = percentHeight<percentWidth?percentHeight:percentWidth;
}
return Math.round(percent);
}
/**
* 获取文件字节流
* @author caiji
* @param fileUrl
* @return byte[]
* @date 2022/1/6 12:40
*/
public static byte[] getFileByte(String fileUrl) throws IOException{
ByteArrayOutputStream bos = new ByteArrayOutputStream();
InputStream in = null;
try{
// 创建URL
URL url = new URL(fileUrl);
byte[] by = new byte[1024];
// 创建链接
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(5000);
in = conn.getInputStream();
int buf_size = 1024;
byte[] buffer = new byte[buf_size];
int len = 0;
while (-1 != (len=in.read(buffer,0,buf_size))){
bos.write(buffer,0,len);
}
return bos.toByteArray();
}catch (IOException e){
e.printStackTrace();
}finally {
try {
in.close();
}catch (IOException e){
e.printStackTrace();
}
bos.close();
}
return null;
}
三、传入图片地址,调用并生成PDF
/**
* 根据图片地址导出PDF
* @author caiji
* @param fileUrl
* @param paperType 纸张类型对象 A4、A3等
* @param response
* @return void
* @date 2022/1/6 12:40
*/
public void imageToPdf(String pdfFileName, List<String> fileUrl, Rectangle paperType, HttpServletResponse response){
try {
//先生成PDF,再进行下载导出
File pdfFile = FileHandleUtil.generatePdfFile(pdfFileName,fileUrl,paperType);
FileHandleUtil.downloadPdfFile(pdfFile, response);
pdfFile.delete();
}catch (Exception e){
e.printStackTrace();
}
}
这块不说太多,方法内的注释都已说明,学习阶段,若有问题请随便提~~~
问题说明:我测试是使用前端传输的Base64转成图片后再处理填充到PDF,处理过程中存在图片有些许失帧问题,这个暂未提供有效处理,还得继续研究文档,网上看的一些都是说这个操作是肯定的有失帧,避免不了。。。。。。