使用itextpdf切割、合并pdf以及合并多個圖檔成為pdf
按頁切割PDF檔案
import java.util.List;
import java.util.Map;
/**
* 切割接口(由于在我們的項目中不止需要切割PDF,還有其他ppt、word等檔案的切割,是以此處給定了一個接口,無需其他檔案類型的可不使用此接口)
*/
public interface ISplit {
List<Map<String, String>> split(String filePath) throws Exception;
}
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.PdfCopy;
import com.itextpdf.text.pdf.PdfImportedPage;
import com.itextpdf.text.pdf.PdfReader;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 切割pdf檔案
*/
@Log4j2
@Component
public class SplitPdf implements ISplit {
//檔案路徑字首
@Value("${filePathPrefix}")
private String filePathPrefix;
//遠端檔案通路域名
@Value("${resources.domain}")
private String resourcesDomain;
@Autowired
public SplitPdf(PptServiceClient pptServiceClient, FileServiceClient fileServiceClient) {
this.pptServiceClient = pptServiceClient;
this.fileServiceClient = fileServiceClient;
}
@SuppressWarnings("unchecked")
@Override
public List<Map<String, String>> split(String filePath) throws Exception {
List<Map<String, String>> mapList = new ArrayList<>();
Document document = null;
PdfCopy copy = null;
//這裡是遠端檔案,是以用的new URL,本地檔案可以直接傳入路徑
PdfReader reader = new PdfReader(new URL(resourcesDomain + filePath));
int n = reader.getNumberOfPages();
for (int i = 1; i <= n; i++) {
String perPagePath = splitPage(reader, filePathPrefix + filePath, i, i);
HashMap<String, String> map = new HashMap<>();
//FileTypeEnum是檔案類型枚舉,可自己實作
map.put(FileTypeEnum.PDF.getType().toLowerCase(), perPagePath);
mapList.add(map);
}
//傳回值可自己指定,此處是本人項目需要
return mapList;
}
private String splitPage(PdfReader reader, String filePath, Integer from, Integer end) throws DocumentException, IOException {
//建立檔案夾路徑(可自己實作)
//FilePathUtil.mkDirsIfNotExists(filePath);
Document document;
PdfCopy copy;
//此處是因為itextpdf在切割時是從1開始的
if (from == 0) {
from = 1;
}
int a = filePath.lastIndexOf("/");
String staticPath = filePath.substring(0, a);
String staticName = filePath.substring(a, filePath.lastIndexOf(".pdf"));
String saveFileName = staticName + "_" + from + ".pdf";
String saveFilePath = staticPath + saveFileName;
document = new Document(reader.getPageSize(1));
copy = new PdfCopy(document, new FileOutputStream(saveFilePath));
document.open();
for (int j = from; j <= end; j++) {
document.newPage();
PdfImportedPage page = copy.getImportedPage(reader, j);
copy.addPage(page);
}
document.close();
return saveFilePath.substring(filePathPrefix.length());
}
}
合并多個PDF檔案
import java.util.List;
/**
* 合并接口
*/
public interface IMerge {
String merge(List<String> filePathList, String toPath);
}
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.PdfCopy;
import com.itextpdf.text.pdf.PdfReader;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URL;
import java.util.Calendar;
import java.util.List;
import java.util.UUID;
/**
* 合并多個PDF
*/
@Log4j2
@Component
public class MergePdf implements IMerge {
@Value("${filePathPrefix}")
private String filePathPrefix;
@Value("${resources.domain}")
private String resourcesDomain;
@Override
public String merge(List<String> filePathList, String toPath) {
try {
Document document = new Document();
if (toPath == null) {
toPath = "/files/upload" + getFilePathByDate() + "/" + UUID.randomUUID().toString().replace("-", "") + ".pdf";
}
FilePathUtil.mkDirsIfNotExists(filePathPrefix + toPath);
OutputStream bos = new FileOutputStream(filePathPrefix + toPath);
PdfCopy copy = new PdfCopy(document, bos);
document.open();
for (String filePath : filePathList) {
PdfReader reader = new PdfReader(new URL(resourcesDomain + filePath));
copy.addDocument(reader);
copy.freeReader(reader);
reader.close();
}
document.close();
} catch (DocumentException | IOException | ResponseException e) {
log.error("合并PDF檔案失敗,msg={}", e.getMessage());
return null;
}
return toPath;
}
private String getFilePathByDate() {
Calendar calendar = Calendar.getInstance();
return "/" + calendar.get(Calendar.YEAR) + "/" + (calendar.get(Calendar.MONTH) + 1);
}
}
合并多張圖檔到PDF檔案
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Image;
import com.itextpdf.text.pdf.PdfWriter;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URL;
import java.util.Calendar;
import java.util.List;
import java.util.UUID;
/**
* 合并圖檔成為PDF
*/
@Log4j2
@Component
public class MergePicture implements IMerge {
@Value("${filePathPrefix}")
private String filePathPrefix;
@Value("${resources.domain}")
private String resourcesDomain;
@Override
public String merge(List<String> filePathList, String toPath) {
try {
Document document = new Document();
if (toPath == null) {
toPath = "/files/upload" + getFilePathByDate() + "/" + UUID.randomUUID().toString().replace("-", "") + ".pdf";
}
FilePathUtil.mkDirsIfNotExists(filePathPrefix + toPath);
OutputStream os = new FileOutputStream(filePathPrefix + toPath);
PdfWriter.getInstance(document, os);
document.open();
for (String filePath : filePathList) {
document.newPage();
BufferedImage img = ImageIO.read(new URL(resourcesDomain + filePath));
int width = img.getWidth();
int height = img.getHeight();
int percent = getPercent2(height, width);
Image image = Image.getInstance(new URL(resourcesDomain + filePath));
//設定圖檔居中
image.setAlignment(Image.MIDDLE);
//設定圖檔縮放百分比,表示顯示的大小是原來圖像的多少比例
image.scalePercent(percent + 3);
document.add(image);
}
document.close();
} catch (IOException | DocumentException e) {
log.error("合并圖檔失敗,msg={}", e.getMessage());
return null;
}
return toPath;
}
/**
* 将每張圖檔統一按照寬度壓縮 這樣來的效果是,所有圖檔的寬度是相等的,自我認為給客戶的效果是最好的
*/
private int getPercent2(float h, float w) {
int p;
float p2;
p2 = 530 / w * 100;
p = Math.round(p2);
return p;
}
/**
* 此處為本人項目中設定的檔案路徑:格式為\files\upload\2022\6\
*/
private String getFilePathByDate() {
Calendar calendar = Calendar.getInstance();
return "/" + calendar.get(Calendar.YEAR) + "/" + (calendar.get(Calendar.MONTH) + 1);
}
}