• Springboot 结合PDF上传到OSS


    目录

     一、首先注册阿里云OSS(新用户免费使用3个月)

    二、步骤

    2.1 将pdf模板上传到oos

    2.2 这里有pdf地址,将读写权限设置为共工读

    ​编辑 三、代码

    3.1 pom.xml

    3.2 配置文件

     3.3 oss model

    3.4 配置类(不需要修改)

    3.5 将配置类放入ioc容器

    3.6 controller

    四、结果

    ​编辑 五、源代码参考


     一、首先注册阿里云OSS(新用户免费使用3个月)

    阿里云OSS 存储对象的注册与使用-CSDN博客

    二、步骤

    2.1 将pdf模板上传到oos

    2.2 这里有pdf地址,将读写权限设置为共工读

     三、代码

    3.1 pom.xml

    1. <dependency>
    2. <groupId>com.itextpdfgroupId>
    3. <artifactId>itext7-coreartifactId>
    4. <version>7.2.5version>
    5. <type>pomtype>
    6. dependency>
    7. <dependency>
    8. <groupId>com.aliyun.ossgroupId>
    9. <artifactId>aliyun-sdk-ossartifactId>
    10. <version>3.10.2version>
    11. dependency>

    3.2 配置文件

    1. # 配置阿里云OSS(application.properties)
    2. aliyun.oss.bucketName = hyc-8147
    3. aliyun.oss.endpoint = oss-cn-beijing.aliyuncs.com
    4. aliyun.oss.accessKeyId = LTAI5tE2krid8AXzidDUpn9n
    5. aliyun.oss.accessKeySecret = 2A0Vrvj982nfRPWDVt3lp
    6. # yml版(application.yml)
    7. #aliyun:
    8. # oss:
    9. # bucketName: hyc-8147
    10. # endpoint: oss-cn-beijing.aliyuncs.com
    11. # accessKeyId: LTAI5tE2krid8AXzidDUpn9n
    12. # accessKeySecret: 2A0Vrvj982nfRPWDVt3lp

     3.3 oss model

    1. package com.by.model;
    2. import lombok.Data;
    3. import org.springframework.boot.context.properties.ConfigurationProperties;
    4. import org.springframework.context.annotation.Configuration;
    5. @Configuration
    6. @ConfigurationProperties(prefix = "aliyun.oss")
    7. @Data
    8. public class AliOssProperties {
    9. private String endpoint;
    10. private String accessKeyId;
    11. private String accessKeySecret;
    12. private String bucketName;
    13. }

    3.4 配置类(不需要修改)

    1. package com.by.util;
    2. import com.aliyun.oss.ClientException;
    3. import com.aliyun.oss.OSS;
    4. import com.aliyun.oss.OSSClientBuilder;
    5. import com.aliyun.oss.OSSException;
    6. import lombok.AllArgsConstructor;
    7. import lombok.Data;
    8. import lombok.extern.slf4j.Slf4j;
    9. import java.io.ByteArrayInputStream;
    10. @Data
    11. @AllArgsConstructor
    12. //固定代码,CV直接使用
    13. public class AliOssUtil {
    14. private String endpoint;
    15. private String accessKeyId;
    16. private String accessKeySecret;
    17. private String bucketName;
    18. /**
    19. * 文件上传
    20. *
    21. * @param bytes :传入的文件要转为byte[]
    22. * @param objectName :表示在oss中存储的文件名字。
    23. * @return
    24. */
    25. public String upload(byte[] bytes, String objectName) {
    26. // 创建OSSClient实例。
    27. OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
    28. try {
    29. // 创建PutObject请求。
    30. ossClient.putObject(bucketName, objectName, new ByteArrayInputStream(bytes));
    31. } catch (OSSException oe) {
    32. System.out.println("Caught an OSSException, which means your request made it to OSS, "
    33. + "but was rejected with an error response for some reason.");
    34. System.out.println("Error Message:" + oe.getErrorMessage());
    35. System.out.println("Error Code:" + oe.getErrorCode());
    36. System.out.println("Request ID:" + oe.getRequestId());
    37. System.out.println("Host ID:" + oe.getHostId());
    38. } catch (ClientException ce) {
    39. System.out.println("Caught an ClientException, which means the client encountered "
    40. + "a serious internal problem while trying to communicate with OSS, "
    41. + "such as not being able to access the network.");
    42. System.out.println("Error Message:" + ce.getMessage());
    43. } finally {
    44. if (ossClient != null) {
    45. ossClient.shutdown();
    46. }
    47. }
    48. //文件访问路径规则 https://BucketName.Endpoint/ObjectName
    49. StringBuilder stringBuilder = new StringBuilder("https://");
    50. stringBuilder
    51. .append(bucketName)
    52. .append(".")
    53. .append(endpoint)
    54. .append("/")
    55. .append(objectName);
    56. return stringBuilder.toString();
    57. }
    58. }

    3.5 将配置类放入ioc容器

    1. package com.by.config;
    2. import com.by.model.AliOssProperties;
    3. import com.by.util.AliOssUtil;
    4. import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
    5. import org.springframework.context.annotation.Bean;
    6. import org.springframework.context.annotation.Configuration;
    7. @Configuration
    8. public class OssConfiguration {
    9. @Bean
    10. @ConditionalOnMissingBean
    11. public AliOssUtil getAliOssUtil(AliOssProperties aliOssProperties) {
    12. // log.info("创建OssUtil");
    13. AliOssUtil aliOssUtil = new AliOssUtil(
    14. aliOssProperties.getEndpoint(),
    15. aliOssProperties.getAccessKeyId(),
    16. aliOssProperties.getAccessKeySecret(),
    17. aliOssProperties.getBucketName()
    18. );
    19. return aliOssUtil;
    20. }
    21. }

    3.6 controller

    1. package com.by.controller;
    2. import com.by.util.AliOssUtil;
    3. import com.itextpdf.forms.PdfAcroForm;
    4. import com.itextpdf.forms.fields.PdfFormField;
    5. import com.itextpdf.kernel.font.PdfFont;
    6. import com.itextpdf.kernel.font.PdfFontFactory;
    7. import com.itextpdf.kernel.geom.PageSize;
    8. import com.itextpdf.kernel.pdf.PdfDocument;
    9. import com.itextpdf.kernel.pdf.PdfReader;
    10. import com.itextpdf.kernel.pdf.PdfWriter;
    11. import org.slf4j.Logger;
    12. import org.slf4j.LoggerFactory;
    13. import org.springframework.beans.factory.annotation.Autowired;
    14. import org.springframework.http.HttpHeaders;
    15. import org.springframework.http.HttpStatus;
    16. import org.springframework.http.MediaType;
    17. import org.springframework.http.ResponseEntity;
    18. import org.springframework.web.bind.annotation.GetMapping;
    19. import org.springframework.web.bind.annotation.RestController;
    20. import javax.servlet.http.HttpServletResponse;
    21. import java.io.*;
    22. import java.net.URL;
    23. import java.nio.file.Files;
    24. import java.nio.file.Path;
    25. import java.nio.file.StandardCopyOption;
    26. import java.util.HashMap;
    27. import java.util.Map;
    28. import java.util.Optional;
    29. @RestController
    30. public class PdfController {
    31. // 初始化日志记录器,用于记录PDF控制器类的操作日志
    32. private static final Logger logger = LoggerFactory.getLogger(PdfController.class);
    33. @Autowired
    34. private AliOssUtil aliOssUtil;
    35. /**
    36. * 生成填充数据的PDF文件并提供下载。
    37. *
    38. * @param response 用于设置HTTP响应信息的ServletResponse对象。
    39. * @return 返回包含填充后PDF文件内容的响应实体。
    40. * @throws IOException 如果处理PDF文件或下载模板文件时发生IO错误。
    41. */
    42. @GetMapping("/download")
    43. public ResponseEntity<byte[]> generateFilledPdf(HttpServletResponse response) throws IOException {
    44. // 准备需要填充到PDF的数据
    45. Map dataMap = new HashMap<>();
    46. dataMap.put("name", "黄哥");
    47. dataMap.put("tel", "175");
    48. // 从URL下载PDF模板并临时保存到本地
    49. String templateUrl = "https://hyc-8147.oss-cn-beijing.aliyuncs.com/3.pdf";
    50. Path tempTemplateFile = Files.createTempFile("temp_template_", ".pdf");
    51. try (InputStream inputStream = new URL(templateUrl).openStream()) {
    52. Files.copy(inputStream, tempTemplateFile, StandardCopyOption.REPLACE_EXISTING);
    53. } catch (IOException e) {
    54. logger.error("Failed to download and save the PDF template from {}", templateUrl, e);
    55. // 下载模板失败时,返回500错误并提供错误信息
    56. return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
    57. .body("Error downloading PDF template. Please try again later.".getBytes());
    58. }
    59. try {
    60. // 使用填充的数据生成新的PDF文件
    61. byte[] pdfBytes = fillPdfData(tempTemplateFile, dataMap);
    62. // 将生成的PDF文件上传到OSS,并设置下载文件名
    63. String downloadFileName = System.currentTimeMillis() + "_filled.pdf";
    64. aliOssUtil.upload(pdfBytes, downloadFileName);
    65. // 设置响应头,提供PDF文件的下载
    66. HttpHeaders headers = new HttpHeaders();
    67. headers.setContentType(MediaType.APPLICATION_PDF);
    68. headers.setContentDispositionFormData("attachment", downloadFileName);
    69. return ResponseEntity.ok().headers(headers).body(pdfBytes);
    70. } finally {
    71. // 清理临时文件
    72. Files.deleteIfExists(tempTemplateFile);
    73. }
    74. }
    75. /**
    76. * 根据提供的数据映射,填充PDF表单并返回填充后的PDF数据。
    77. *
    78. * @param sourcePdf 表单源PDF文件的路径。
    79. * @param dataMap 需要填充到PDF表单的数据映射,键为表单字段名称,值为填充的文本。
    80. * @return 填充后的PDF数据的字节数组。
    81. * @throws IOException 如果读取或处理PDF文件时发生错误。
    82. */
    83. private byte[] fillPdfData(Path sourcePdf, Map dataMap) throws IOException {
    84. // 使用try-with-resources语句确保资源正确关闭
    85. try (InputStream fileInputStream = Files.newInputStream(sourcePdf);
    86. PdfReader pdfReader = new PdfReader(fileInputStream);
    87. ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
    88. // 初始化PDF文档并设置页面大小
    89. PdfDocument pdf = new PdfDocument(pdfReader, new PdfWriter(outputStream));
    90. pdf.setDefaultPageSize(PageSize.A4);
    91. // 获取PDF表单并填充数据
    92. PdfAcroForm form = PdfAcroForm.getAcroForm(pdf, true);
    93. Map fields = form.getFormFields();
    94. // 设置表单字段使用的字体
    95. PdfFont currentFont = PdfFontFactory.createFont("STSong-Light", "UniGB-UCS2-H", PdfFontFactory.EmbeddingStrategy.PREFER_NOT_EMBEDDED);
    96. // 填充表单字段
    97. dataMap.forEach((key, value) -> {
    98. Optional.ofNullable(fields.get(key))
    99. .ifPresent(formField -> formField.setFont(currentFont).setValue(value));
    100. });
    101. // 将表单字段合并到PDF文档中,防止编辑
    102. form.flattenFields();
    103. // 关闭PDF文档并返回填充后的PDF数据
    104. pdf.close();
    105. return outputStream.toByteArray();
    106. } catch (Exception e) {
    107. logger.error("Error filling PDF data: {}", e.getMessage());
    108. // 抛出IOException,封装原始异常
    109. throw new IOException("Failed to fill PDF data due to an internal error.", e);
    110. }
    111. }
    112. }

    四、结果

     五、源代码参考

    源代码我已经放入了云效

    https://codeup.aliyun.com/62858d45487c500c27f5aab5/huang-spring-boot-pdf.git

  • 相关阅读:
    箩筐递馒头
    并查集总结
    A星寻路优化方案
    油猴浏览器(安卓)
    记一次相同sql语句,java中执行不成功,数据库中能执行成功的问题
    计算机毕业设计(附源码)python钟点工管理系统
    Domain Admin域名和SSL证书过期监控到期提醒
    基于Zookeeper实现高可用架构
    20天拿下华为OD笔试之【模拟】2023B-阿里巴巴找黄金宝箱(1)【欧弟算法】全网注释最详细分类最全的华为OD真题题解
    mysql 8.0.17 解压版安装教程
  • 原文地址:https://blog.csdn.net/qq_65142821/article/details/137992630