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

   <!--导入支持pdf的依赖 -->
        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itext7-core</artifactId>
            <version>7.2.5</version>
            <type>pom</type>
        </dependency>
 <!--引入阿里云oss依赖 -->
        <dependency>
            <groupId>com.aliyun.oss</groupId>
            <artifactId>aliyun-sdk-oss</artifactId>
            <version>3.10.2</version>
        </dependency>

3.2 配置文件

# 配置阿里云OSS(application.properties)
aliyun.oss.bucketName = hyc-8147
aliyun.oss.endpoint = oss-cn-beijing.aliyuncs.com
aliyun.oss.accessKeyId = LTAI5tE2krid8AXzidDUpn9n
aliyun.oss.accessKeySecret = 2A0Vrvj982nfRPWDVt3lp

# yml版(application.yml)
#aliyun:
#  oss:
#    bucketName: hyc-8147
#    endpoint: oss-cn-beijing.aliyuncs.com
#    accessKeyId: LTAI5tE2krid8AXzidDUpn9n
#    accessKeySecret: 2A0Vrvj982nfRPWDVt3lp

 3.3 oss model

package com.by.model;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
 
@Configuration
@ConfigurationProperties(prefix = "aliyun.oss")
@Data
public class AliOssProperties {
 
    private String endpoint;
    private String accessKeyId;
    private String accessKeySecret;
    private String bucketName;
 
 
}

3.4 配置类(不需要修改)

package com.by.util;

import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import java.io.ByteArrayInputStream;
 
@Data
@AllArgsConstructor
//固定代码,CV直接使用
public class AliOssUtil {
 
    private String endpoint;
    private String accessKeyId;
    private String accessKeySecret;
    private String bucketName;
 
    /**
     * 文件上传
     *
     * @param bytes :传入的文件要转为byte[]
     * @param objectName :表示在oss中存储的文件名字。
     * @return
     */
    public String upload(byte[] bytes, String objectName) {
 
        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
 
        try {
            // 创建PutObject请求。
            ossClient.putObject(bucketName, objectName, new ByteArrayInputStream(bytes));
        } catch (OSSException oe) {
            System.out.println("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            System.out.println("Error Message:" + oe.getErrorMessage());
            System.out.println("Error Code:" + oe.getErrorCode());
            System.out.println("Request ID:" + oe.getRequestId());
            System.out.println("Host ID:" + oe.getHostId());
        } catch (ClientException ce) {
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message:" + ce.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
 
        //文件访问路径规则 https://BucketName.Endpoint/ObjectName
        StringBuilder stringBuilder = new StringBuilder("https://");
        stringBuilder
                .append(bucketName)
                .append(".")
                .append(endpoint)
                .append("/")
                .append(objectName);
 
        return stringBuilder.toString();
    }
}

3.5 将配置类放入ioc容器

package com.by.config;


import com.by.model.AliOssProperties;
import com.by.util.AliOssUtil;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class OssConfiguration {
    @Bean
    @ConditionalOnMissingBean
    public AliOssUtil getAliOssUtil(AliOssProperties aliOssProperties) {
//        log.info("创建OssUtil");
        AliOssUtil aliOssUtil = new AliOssUtil(
                aliOssProperties.getEndpoint(),
                aliOssProperties.getAccessKeyId(),
                aliOssProperties.getAccessKeySecret(),
                aliOssProperties.getBucketName()
        );
        return aliOssUtil;
    }
}

3.6 controller

package com.by.controller;

import com.by.util.AliOssUtil;
import com.itextpdf.forms.PdfAcroForm;
import com.itextpdf.forms.fields.PdfFormField;
import com.itextpdf.kernel.font.PdfFont;
import com.itextpdf.kernel.font.PdfFontFactory;
import com.itextpdf.kernel.geom.PageSize;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfReader;
import com.itextpdf.kernel.pdf.PdfWriter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

@RestController
public class PdfController {
    // 初始化日志记录器,用于记录PDF控制器类的操作日志
    private static final Logger logger = LoggerFactory.getLogger(PdfController.class);

    @Autowired
    private AliOssUtil aliOssUtil;

    /**
     * 生成填充数据的PDF文件并提供下载。
     *
     * @param response 用于设置HTTP响应信息的ServletResponse对象。
     * @return 返回包含填充后PDF文件内容的响应实体。
     * @throws IOException 如果处理PDF文件或下载模板文件时发生IO错误。
     */
    @GetMapping("/download")
    public ResponseEntity<byte[]> generateFilledPdf(HttpServletResponse response) throws IOException {
        // 准备需要填充到PDF的数据
        Map<String, String> dataMap = new HashMap<>();
        dataMap.put("name", "黄哥");
        dataMap.put("tel", "175");

        // 从URL下载PDF模板并临时保存到本地
        String templateUrl = "https://hyc-8147.oss-cn-beijing.aliyuncs.com/3.pdf";
        Path tempTemplateFile = Files.createTempFile("temp_template_", ".pdf");

        try (InputStream inputStream = new URL(templateUrl).openStream()) {
            Files.copy(inputStream, tempTemplateFile, StandardCopyOption.REPLACE_EXISTING);
        } catch (IOException e) {
            logger.error("Failed to download and save the PDF template from {}", templateUrl, e);
            // 下载模板失败时,返回500错误并提供错误信息
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                    .body("Error downloading PDF template. Please try again later.".getBytes());
        }
        try {
            // 使用填充的数据生成新的PDF文件
            byte[] pdfBytes = fillPdfData(tempTemplateFile, dataMap);

            // 将生成的PDF文件上传到OSS,并设置下载文件名
            String downloadFileName = System.currentTimeMillis() + "_filled.pdf";
            aliOssUtil.upload(pdfBytes, downloadFileName);

            // 设置响应头,提供PDF文件的下载
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_PDF);
            headers.setContentDispositionFormData("attachment", downloadFileName);
            return ResponseEntity.ok().headers(headers).body(pdfBytes);
        } finally {
            // 清理临时文件
            Files.deleteIfExists(tempTemplateFile);
        }
    }


    /**
     * 根据提供的数据映射,填充PDF表单并返回填充后的PDF数据。
     *
     * @param sourcePdf 表单源PDF文件的路径。
     * @param dataMap   需要填充到PDF表单的数据映射,键为表单字段名称,值为填充的文本。
     * @return 填充后的PDF数据的字节数组。
     * @throws IOException 如果读取或处理PDF文件时发生错误。
     */
    private byte[] fillPdfData(Path sourcePdf, Map<String, String> dataMap) throws IOException {
        // 使用try-with-resources语句确保资源正确关闭
        try (InputStream fileInputStream = Files.newInputStream(sourcePdf);
             PdfReader pdfReader = new PdfReader(fileInputStream);
             ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {

            // 初始化PDF文档并设置页面大小
            PdfDocument pdf = new PdfDocument(pdfReader, new PdfWriter(outputStream));
            pdf.setDefaultPageSize(PageSize.A4);

            // 获取PDF表单并填充数据
            PdfAcroForm form = PdfAcroForm.getAcroForm(pdf, true);
            Map<String, PdfFormField> fields = form.getFormFields();

            // 设置表单字段使用的字体
            PdfFont currentFont = PdfFontFactory.createFont("STSong-Light", "UniGB-UCS2-H", PdfFontFactory.EmbeddingStrategy.PREFER_NOT_EMBEDDED);

            // 填充表单字段
            dataMap.forEach((key, value) -> {
                Optional.ofNullable(fields.get(key))
                        .ifPresent(formField -> formField.setFont(currentFont).setValue(value));
            });

            // 将表单字段合并到PDF文档中,防止编辑
            form.flattenFields();

            // 关闭PDF文档并返回填充后的PDF数据
            pdf.close();

            return outputStream.toByteArray();
        } catch (Exception e) {
            logger.error("Error filling PDF data: {}", e.getMessage());
            // 抛出IOException,封装原始异常
            throw new IOException("Failed to fill PDF data due to an internal error.", e);
        }
    }

}

四、结果

 五、源代码参考

源代码我已经放入了云效

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

  • 9
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: 前端使用HTML5的File API获取用户选择的图片,然后将图片转成二进制流,通过Ajax请求发送给后端。 后端使用阿里云OSS SDK,上传图片到OSS。具体步骤如下: 1. 引入阿里云OSS SDK依赖: ``` <dependency> <groupId>com.aliyun.oss</groupId> <artifactId>aliyun-sdk-oss</artifactId> <version>3.10.2</version> </dependency> ``` 2. 在Springboot配置文件中配置OSS相关参数: ``` oss.endpoint=oss-cn-hangzhou.aliyuncs.com oss.accessKeyId=your_access_key_id oss.accessKeySecret=your_access_key_secret oss.bucketName=your_bucket_name ``` 3. 在Controller中编写上传图片的接口: ``` @PostMapping("/upload") public String upload(@RequestParam("file") MultipartFile file) throws IOException { // 获取文件名 String fileName = file.getOriginalFilename(); // 上传到OSS OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret); ossClient.putObject(bucketName, fileName, file.getInputStream()); // 关闭OSS客户端 ossClient.shutdown(); // 返回图片URL return "https://" + bucketName + "." + endpoint + "/" + fileName; } ``` 4. 前端通过Ajax请求上传图片: ``` function uploadImage() { var file = document.getElementById("file").files[0]; var formData = new FormData(); formData.append("file", file); $.ajax({ url: "/upload", type: "POST", data: formData, processData: false, contentType: false, success: function(data) { console.log(data); } }); } ``` 需要注意的是,前端上传的文件大小可能比较大,需要在后端进行文件大小和类型的校验,防止恶意攻击和服务器压力过大。 ### 回答2: 前端上传图片到Spring Boot后端,然后后端将图片上传到OSS(Object Storage Service)中。 首先,前端需要通过一个表单页面或者其他方式选择要上传的图片。当用户选择完成后,前端可以使用一个AJAX请求将图片发送给后端。 在后端,我们需要配置一个用于接收图片并上传到OSS的路由或API接口。这个接口需要处理用户上传的图片文件,并将其保存到本地的临时文件夹中。 然后,我们需要引入相应的OSS客户端库,比如阿里云的OSS SDK。在后端中,我们需要配置OSS的相关信息,比如Access Key ID(访问密钥ID)、Access Key Secret(访问密钥密码)、OSS域名等。 接下来,我们需要将保存在本地的临时文件传到OSS。首先,我们需要创建一个OSSClient对象,使用OSSClient的构造函数传入配置的OSS相关信息。 然后,我们可以调用OSSClient对象的putObject方法来上传图片。在putObject方法中,我们需要指定要上传的目标Bucket(OSS存储空间),以及目标图片的存储路径和文件名。同时,我们也需要指定要上传的文件的本地路径。 上传完成后,我们可以在OSS中看到上传的图片。 最后,在后端中,我们可以返回一个上传成功的消息或者其他相应的数据给前端,以表示图片上传到OSS的状态。 总结而言,前端上传图片到Spring Boot后端,后端将图片上传到OSS步骤包括:前端选择图片并上传至后端,后端保存图片到本地临时文件夹,配置OSS并引入相关OSS客户端库,创建OSSClient对象并使用putObject方法将图片上传至OSS,返回上传成功的消息给前端。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

今天的接口写完了吗?

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值