• Java 利用pdfbox将图片和成到pdf指定位置


    业务背景:用户在手机APP上进行签名,前端将签完名字的图片传入后端,后端合成新的pdf.

    废话不多说,上代码:

    1. //控制层代码
    2. @PostMapping("/imageToPdf")
    3. public Result imageToPdf(@RequestParam("linkName") String name, @RequestParam("file")
    4. MultipartFile file) throws IOException {
    5. try {
    6. String format = LocalDateTimeUtil.format(LocalDateTime.now(),
    7. DatePattern.PURE_DATETIME_MS_PATTERN);
    8. File f = convertMultipartFileToFile(file);
    9. //缩放图片
    10. ImgUtil.scale(FileUtil.file(f), FileUtil.file("/hetong/dev/image/" + format +
    11. ".png"), 0.06f);
    12. // 旋转270度
    13. BufferedImage image = (BufferedImage)
    14. //此处利用hutool工具类进行缩放
    15. ImgUtil.rotate(ImageIO.read(FileUtil.file("/hetong/dev/image/" + format +
    16. ".png")), 270);
    17. ImgUtil.write(image, FileUtil.file("/hetong/dev/image/" + format + "_result" +
    18. ".png"));
    19. String imagePath = "/hetong/dev/image/" + format + "_result" + ".png";
    20. String fileUrl = name; // 要下载的文件的HTTPS链接
    21. String localFilePath = "/hetong/dev/" + format + ".pdf"; // 下载文件保存到本地的路径和名称
    22. //String localFilePath = "D:\\soft\\ceshi\\" + format + ".pdf"; // 下载文件保存到本地的路径和名称
    23. downloadFile(fileUrl, localFilePath);
    24. String pdfPath = localFilePath;
    25. String url = imageToPdfUtil.addImageToPDF(imagePath, pdfPath, format);
    26. return new Result(ResultCode.SUCCESS, url);
    27. } catch (IOException e) {
    28. e.printStackTrace();
    29. }
    30. return new Result(ResultCode.IMAGE_MERGE_FAILED, "");
    31. }
    32. //工具类
    33. @Component
    34. public class ImageToPdfUtil {
    35. private static Logger logger = LoggerFactory.getLogger(WordUtil.class);
    36. @Autowired
    37. private UploadManager uploadManager;
    38. @Autowired
    39. private Auth auth;
    40. @Value("${qiniu.bucketName}")
    41. private String bucketName;
    42. @Value("${qiniu.path}")
    43. private String url;
    44. /**
    45. * 添加图片至pdf指定位置
    46. *
    47. * @param imagePath
    48. * @param pdfPath
    49. * @throws IOException
    50. */
    51. public String addImageToPDF(String imagePath, String pdfPath, String format) throws IOException {
    52. // 加载图片
    53. PDDocument document = PDDocument.load(new File(pdfPath));
    54. PDPage lastPage = document.getPage(document.getNumberOfPages() - 1);
    55. PDImageXObject image = PDImageXObject.createFromFile(imagePath, document);
    56. // 获取图片宽度和高度
    57. float imageWidth = image.getWidth();
    58. float imageHeight = image.getHeight();
    59. try (PDPageContentStream contentStream = new PDPageContentStream(document, lastPage, PDPageContentStream.AppendMode.APPEND, true, true)) {
    60. // 设置图片位置
    61. float x = (lastPage.getMediaBox().getWidth() / 2f - imageWidth / 2f) * 0.88f;
    62. float y = (lastPage.getMediaBox().getHeight() / 2f - imageHeight / 2f) * 1.5f;
    63. // 添加图片到指定位置
    64. contentStream.drawImage(image, x, y, imageWidth, imageHeight);
    65. }
    66. // 保存修改后的 PDF
    67. document.save(pdfPath);
    68. document.close();
    69. return uploadQiniu(format);
    70. }
    71. /**
    72. * 上传到七牛云
    73. *
    74. * @param fileName
    75. * @return
    76. * @throws FileNotFoundException
    77. * @throws QiniuException
    78. */
    79. public String uploadQiniu(String fileName) throws FileNotFoundException, QiniuException {
    80. //这里是上传到服务器路径下的,已经填充完数据的word
    81. File file = ResourceUtils.getFile("/hetong/dev/" + fileName + ".pdf");
    82. //File file = ResourceUtils.getFile("D:\\soft\\ceshi\\" + fileName + ".pdf");
    83. //FileInputStream uploadFile = (FileInputStream) file.getInputStream();
    84. // 获取文件输入流
    85. FileInputStream inputStream = new FileInputStream(file);
    86. //这个是已经填充完整的数据后上传至七牛云链接
    87. String path = "http://" + upload(inputStream, fileName);
    88. logger.info("上传至七牛云的合同路径==path==" + path);
    89. return path;
    90. }
    91. public String upload(FileInputStream file, String fileName) throws QiniuException {
    92. String token = auth.uploadToken(bucketName);
    93. Response res = uploadManager.put(file, fileName, token, null, null);
    94. if (!res.isOK()) {
    95. throw new RuntimeException("上传七牛云出错:" + res);
    96. }
    97. return url + "/" + fileName;
    98. }
    99. public static void main(String[] args) {
    100. try {
    101. // 指定原始图片路径
    102. File originalImage = new File("D:\\soft\\ceshi\\20230901204201606.png");
    103. // 指定压缩后保存的目标路径
    104. File compressedImage = new File("D:\\soft\\ceshi\\20230901204201606_result.png");
    105. // 压缩和缩放图片
    106. Thumbnails.of(originalImage)
    107. .scale(0.1) // 缩放比例为50%
    108. .outputQuality(0.9) // 图片质量为80%
    109. .toFile(compressedImage);
    110. System.out.println("图片压缩和缩放完成!");
    111. } catch (IOException e) {
    112. e.printStackTrace();
    113. }
    114. }
    115. /**
    116. * MultipartFile 转file
    117. *
    118. * @param multipartFile
    119. * @return
    120. * @throws IOException
    121. */
    122. public static File convertMultipartFileToFile(MultipartFile multipartFile) throws IOException {
    123. byte[] fileBytes = multipartFile.getBytes();
    124. File tempFile = File.createTempFile("temp", null);
    125. try (OutputStream outputStream = new FileOutputStream(tempFile)) {
    126. outputStream.write(fileBytes);
    127. }
    128. return tempFile;
    129. }
    130. /**
    131. * 根号https链接下载文档
    132. *
    133. * @param fileUrl
    134. * @param localFilePath
    135. * @throws IOException
    136. */
    137. public static void downloadFile(String fileUrl, String localFilePath) throws IOException {
    138. URL url = new URL(fileUrl);
    139. HttpURLConnection connection = (HttpURLConnection) url.openConnection();
    140. connection.setRequestMethod("GET");
    141. BufferedInputStream inputStream = new BufferedInputStream(connection.getInputStream());
    142. FileOutputStream outputStream = new FileOutputStream(localFilePath);
    143. byte[] buffer = new byte[1024];
    144. int bytesRead;
    145. while ((bytesRead = inputStream.read(buffer)) != -1) {
    146. outputStream.write(buffer, 0, bytesRead);
    147. }
    148. outputStream.close();
    149. inputStream.close();
    150. connection.disconnect();
    151. }
    152. }

    注意:前端传过来的图片必须是透明的,否则合成的时候签名处会有边框
         

     

  • 相关阅读:
    JS——经典案例
    小程序轻松实现IM即时通讯多人聊天室
    Coursera Algorithm Ⅱ week1 WordNet
    Java集合相关总结(List | Set | Map)
    Android Glide照片宫格RecyclerView,点击SharedElement共享元素动画查看大图,Kotlin(1)
    CADD课程学习(5)-- 构建靶点已知的化合结构(ChemDraw)
    如何成为开源组件库NutUI的contributor:解决issue并提交PR
    linux fio磁盘性能测试工具使用指南和示例大全
    常见内置函数
    2022前端面试题上岸手册-HTML+CSS部分
  • 原文地址:https://blog.csdn.net/hyddhy/article/details/132695565