Java quickly merges pdf, including pdfbox and itext (millisecond level)

Foreword: In the process of merging pictures into pdf, you can use **ImageIO.read()** method, this method will consume a lot of time to read pictures, try to control the time of merging pdf within 1 second

1. Import dependencies

 <dependency>
            <groupId>org.apache.pdfbox</groupId>
            <artifactId>fontbox</artifactId>
            <version>2.0.12</version>
        </dependency>
        <dependency>
            <groupId>org.apache.pdfbox</groupId>
            <artifactId>pdfbox</artifactId>
            <version>2.0.12</version>
        </dependency>
         <!-- https://mvnrepository.com/artifact/com.itextpdf/itextpdf -->
        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itextpdf</artifactId>
            <version>5.5.5</version>
        </dependency>

        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itext-asian</artifactId>
            <version>5.2.0</version>
        </dependency>

2. pdfbox method

2.1. Merge pictures into pdf

private static byte[] getPdfBytes(MultipartFile[] imagesFiles) throws IOException {<!-- -->
PDDocument document = new PDDocument();
for (MultipartFile datum : imagesFiles) {<!-- -->
String filename = datum. getOriginalFilename();
String fileSuffix = filename. substring(filename. lastIndexOf(".") + 1);
Iterator readers = ImageIO.getImageReadersByFormatName(fileSuffix);
ImageReader reader = (ImageReader) readers. next();
ImageInputStream input = ImageIO.createImageInputStream(datum.getInputStream());
reader.setInput(input, true);
int width = reader. getWidth(0);
int height = reader. getHeight(0);
PDPage pdPage = new PDPage(new PDRectangle(width, height));
document. addPage(pdPage);
PDImageXObject pdImageXObject = PDImageXObject.createFromByteArray(document, datum.getBytes(), "Build image error");
//If there is no byte array of the file, you can also use the following
//String imagePath = "/test";
//PDImageXObject pdImageXObject = PDImageXObject.createFromFile(imagePath, document);
//If there is only url, you can use the HttpUtil method of the hutool package to download it, and the result is a byte array, but it will take a long time
PDPageContentStream contentStream = new PDPageContentStream(document, pdPage);
// write picture
contentStream. drawImage(pdImageXObject, 0, 0);
contentStream. close();
}
ByteArrayOutputStream output = new ByteArrayOutputStream();
document. save(output);
document. close();
return output.toByteArray();
}

2.2. pdf + image conversion to pdf

It is very simple to directly add the above PDDocument document = new PDDocument();
replace with
//Read and upload pdf file
      PDDocument document = PDDocument.load(pdfFile.getInputStream()); //pdfFile is also a MultipartFile, here you can just read the pdf file stream directly
      The following code is the same as the above method

2.3. Read the picture of pdf

/**
* @Author: chl
* @ Date: Created in 14:40 2023/3/1
* @ Description: Can be changed to return value as List<byte[]>
* @param imageFolderPath store image file path
* @param pdfSourcePath The pdf path that needs to be read
* @param dpi The larger this is, the clearer the picture is, 300 is quite clear
* @param formatName
* @ return void
*/
public static void loadPdf2Image(String imageFolderPath, String pdfSourcePath, int dpi, String formatName) throws Exception {<!-- -->
PDDocument document = PDDocument. load(new File(pdfSourcePath));
PDFRenderer renderer = new PDFRenderer(document);
for (int i = 0; i < document. getNumberOfPages(); i ++ ) {<!-- -->
BufferedImage bufferedImage = renderer.renderImageWithDPI(i, dpi);
String imagePath = imageFolderPath + i + "." + formatName;
FileOutputStream fileOutputStream = new FileOutputStream(imagePath);
ImageIO.write(bufferedImage, formatName, fileOutputStream);
}
document. close();
}

3. itext mode

3.1. Image merge pdf

/**
* @Author: chl
* @ Date: Created in 11:08 2023/3/2
* @Description: double the performance
* @param data
* @ return byte[]
*/
public static byte[] multipartFile2pdf2(MultipartFile[] data) {<!-- -->
Document document = new Document();
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try {<!-- -->
PdfWriter. getInstance(document, bos);
document. open();
for (MultipartFile datum : data) {<!-- -->
Image image = null;
ImageInputStream input = null;
int width = 0;
int height = 0;
try {<!-- -->
String filename = datum. getOriginalFilename();
String fileSuffix = filename. substring(filename. lastIndexOf(".") + 1);
Iterator readers = ImageIO.getImageReadersByFormatName(fileSuffix);
ImageReader reader = (ImageReader) readers. next();
input = ImageIO.createImageInputStream(datum.getInputStream());
reader.setInput(input, true);
width = reader. getWidth(0);
height = reader. getHeight(0);
//load image
image = Image.getInstance(datum.getBytes());
//If you can't get the image byte array directly, you can do it directly instead of using FileOutputStream to read it
//image = Image.getInstance(filePath);
// centered
image.setAlignment(Image.MIDDLE);
} catch (BaseException e) {<!-- -->
throw new BaseException("Error loading and uploading pictures");
}
//The page size is the size of the picture, and the position of the newPage cannot be swapped, otherwise a bad picture will be generated
document.setPageSize(new Rectangle(width, height));
document. newPage();
document. add(image);
input. close();
}
document. close();
} catch (BaseException be) {<!-- -->
throw new BaseException("Error loading and uploading pictures");
} catch (Exception e) {<!-- -->
e.printStackTrace();
}
return bos.toByteArray();
}

3.2. Image + pdf combined into pdf

public static byte[] pdfAndImage2Pdf(MultipartFile pdfFile, MultipartFile[] imagesFiles) throws IOException {<!-- -->
PdfReader pdfReader = null;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
PdfStamper pdfStamper = null;
try {<!-- -->
//load pdf
pdfReader = new PdfReader(pdfFile. getBytes());
//Open the pdf editor
pdfStamper = new PdfStamper(pdfReader, bos);

for (MultipartFile datum : imagesFiles) {<!-- -->
String filename = datum. getOriginalFilename();
String fileSuffix = filename. substring(filename. lastIndexOf(".") + 1);
Iterator readers = ImageIO.getImageReadersByFormatName(fileSuffix);
ImageReader reader = (ImageReader) readers. next();
ImageInputStream input = ImageIO.createImageInputStream(datum.getInputStream());
reader.setInput(input, true);
int width = reader. getWidth(0);
int height = reader. getHeight(0);
Image image = Image.getInstance(datum.getBytes());
image.setAlignment(Image.MIDDLE);
//Add a blank page
pdfStamper.insertPage(pdfReader.getNumberOfPages() + 1, new Rectangle(width, height));
// capture blank page
PdfContentByte overContent = pdfStamper.getOverContent(pdfReader.getNumberOfPages());
image.scaleAbsolute(width, height);
//set absolute position
image.setAbsolutePosition(0, 0);
overContent. addImage(image);
input. close();
}

} catch (Exception e) {<!-- -->
e.printStackTrace();
} finally {<!-- -->
try {<!-- -->
pdfStamper. close();
pdfReader. close();
} catch (Exception e) {<!-- -->
e.printStackTrace();
}
}
return bos.toByteArray();
}