-> convert PDF,
-> sign PDF
-> do both conversion and signature
Implementation for conversion is the following :
- Code: Select all
@Override
public PdfDto convert(PdfDto pdfDto) throws IOException {
DataDto dataDto;
try (ByteArrayOutputStream pdfConvertedStream = convertStream(pdfDto)) {
String pdf64Converted = new Base64().encodeAsString(pdfConvertedStream.toByteArray());
dataDto = DataDto.builder()
.fileName(pdfDto.getData().getMultipart().getOriginalFilename())
.pdf(pdf64Converted)
.converted(Boolean.TRUE)
.build();
} catch (UnsupportedFormatException | IOException e) {
// exception thrown
}
return PdfDto.builder()
.headerData(modelMapper.map(logDto, HeaderDataDto.class))
.data(dataDto)
.build();
}
My convert stream is the following:
- Code: Select all
private ByteArrayOutputStream convertStream(PdfDto pdfDto) throws IOException {
ByteArrayOutputStream pdfConvertedStream = new ByteArrayOutputStream();
PdfStandardsConverter converter = new PdfStandardsConverter(
pdfDto.getData().getMultipart().getInputStream());
DataDto dataDto = pdfDto.getData();
PdfFormatEnum pdfFormatEnum = Arrays.stream(PdfFormatEnum.values())
.filter(pdfFormat -> pdfFormat.name().equalsIgnoreCase(dataDto.getFormat()))
.findAny()
.orElse(PdfFormatEnum.PDFA3A);
String pdfFormat = pdfFormatEnum.getFormat().toLowerCase();
switch (pdfFormat) {
case "pdfa1a" -> converter.toPdfA1A(pdfConvertedStream);
case "pdfa1b" -> converter.toPdfA1B(pdfConvertedStream);
case "pdfa2a" -> converter.toPdfA2A(pdfConvertedStream);
case "pdfa2b" -> converter.toPdfA2B(pdfConvertedStream);
case "pdfa3a" -> converter.toPdfA3A(pdfConvertedStream);
// case "pdfa3b" -> converter.toPdfA3B(pdfConvertedStream);
default -> converter.toPdfA3B(pdfConvertedStream);
}
return pdfConvertedStream;
}
For signature :
- Code: Select all
private ByteArrayOutputStream signedStream(PdfDto pdfDto)
throws IOException {
if ((pdfDto.getData().getSignatureName() == null) || pdfDto.getData().getSignatureName().isEmpty()) {
pdfDto.getData().setSignatureName("Signature");
}
return signedStream(pdfDto, pdfDto.getData().getMultipart().getInputStream());
}
private ByteArrayOutputStream signedStream(
PdfDto pdfDto,
InputStream signatureStream) throws IOException {
PdfDocument doc = new PdfDocument(signatureStream);
PdfCertificate cert = new PdfCertificate(IOUtils.toByteArray(FileUtils.base64DecodeFromString(
pdfDto.getData().getCertificate())), pdfDto.getData().getPassword());
PdfSignature pdfSign = new PdfSignature(
doc,
doc.getPages().get(doc.getPages().getCount() - 1),
cert,
pdfDto.getData().getSignatureName());
pdfSign.setDocumentPermissions(PdfCertificationFlags.Forbid_Changes);
pdfSign.setDocumentPermissions(PdfCertificationFlags.Allow_Form_Fill);
pdfSign.setLocationInfo(pdfDto.getData().getLocation());
pdfSign.setReason(pdfDto.getData().getReason());
ByteArrayOutputStream signedPdf = new ByteArrayOutputStream();
doc.saveToStream(signedPdf);
doc.close();
return signedPdf;
}
My issue is that once deployed, Tomcat consumes over than 9Go of RAM and crashes when sending heavy PDF (over 40Mo)...
Unit tests work fine in my web service when testing:
-> Controllers (MockMvc)
-> Service layer
My errors are coming when solution is deployed and that I call the entrypoint (using OkHTTP Client).
Currently springboot version used is 3.2.5 and spirePDF 9.6.2.
The second issue is that memory issue were not encountered using unit tests...
I have those issue when a java client is calling to entry point.
The problem occurs on conversion : PdfStandardsConverter and
The same issue occurs on signature too