Java实现动态生成word报告

Java实现动态生成word报告

1.准备好docx文件模板

举例:动态生成表格数据,以下是list数组类型的freemarker语法

在这里插入图片描述

将写好的word模板加入到templates目录下
在这里插入图片描述

2.在pom.xml中导入相关依赖
		<dependency>
			<groupId>fr.opensagres.xdocreport</groupId>
			<artifactId>fr.opensagres.xdocreport.document.docx</artifactId>
			<version>2.0.3</version>
		</dependency>
            <dependency>
			<groupId>io.minio</groupId>
			<artifactId>minio</artifactId>
			<version>8.2.1</version>
		</dependency>
3.关于Minio的介绍

Minio 是一个开源的对象存储服务器,可用于存储和访问海量数据。以下是 Minio 的基本用法:

(1)安装 Minio

首先,你需要下载和安装 Minio。你可以从 Minio 的官方网站(https://min.io/)下载适用于你的操作系统的安装包,然后按照 Minio 的安装说明进行操作。

(2)启动 Minio

安装完成后,你可以通过运行以下命令来启动 Minio:

bash复制代码

minio server /path/to/data

其中 /path/to/data 是你用于存储数据的目录或磁盘空间。

(3)访问 Minio

一旦 Minio 启动成功,你就可以使用 Web 浏览器、命令行工具或 SDK 来访问和操作 Minio。

  • Web 浏览器:在浏览器中输入 Minio 的访问地址(默认为 localhost:9000),即可看到 Minio 的管理界面。你可以使用默认的用户名和密码(分别为 miniominio123)登录。
  • 命令行工具:你可以使用 Minio 提供的命令行工具(如 mcbs)来访问和操作 Minio。这些工具提供了丰富的命令行选项和 SDK,方便你进行数据的上传、下载、备份、恢复等操作。
  • SDK:Minio 还提供了多种编程语言的 SDK,如 Java、Python、Go、JavaScript 等。你可以使用这些 SDK 在应用程序中集成 Minio 的功能,以便更方便地管理和操作数据。

总之,使用 Minio 可以通过简单的安装和配置,快速构建一个可靠的对象存储服务,方便你存储和访问海量数据。

4.在application.yml中添加Minio配置
minio:
//host和port自行填写
  endpoint: http://127.0.0.1:9000
  accessKey: minio
  secretKey: minio123
  bucketName: carbon
  expires: 86400

5.导入MinioConfig配置类
@Data
@Configuration
public class MinioConfig {

    @Value("${minio.endpoint}")
    private String endpoint;

    @Value("${minio.bucketName}")
    private String bucketName;

    @Value("${minio.accessKey}")
    private String accessKey;

    @Value("${minio.secretKey}")
    private String secretKey;

    @Value("${minio.expires}")
    private Integer expires = 86400;

}

6.导入UploadFileService类与其实现类UploadFileServiceImpl(直接CV过去)
public interface UploadFileService {

    void createBucket(String bucketName);

    /**
     * 获取全部bucket
     * <p>
     * https://docs.minio.io/cn/java-client-api-reference.html#listBuckets
     */
    List<Bucket> getAllBuckets();

    /**
     * 根据bucketName获取信息
     *
     * @param bucketName bucket名称
     */
    // @SneakyThrows
    Optional<Bucket> getBucket(String bucketName);

    /**
     * 根据bucketName删除信息
     *
     * @param bucketName bucket名称
     */
    void removeBucket(String bucketName);

    /**
     * 根据文件前置查询文件
     *
     * @param bucketName bucket名称
     * @param prefix     前缀
     * @param recursive  是否递归查询
     * @return MinioItem 列表
     */
    List getAllObjectsByPrefix(String bucketName, String prefix, boolean recursive);

    /**
     * 获取文件外链
     *
     * @param bucketName bucket名称
     * @param objectName 文件名称
     * @param expires    过期时间 <=7
     * @return url
     */
    String getObjectURL(String bucketName, String objectName, Integer expires);

    /**
     * 获取文件
     *
     * @param bucketName bucket名称
     * @param objectName 文件名称
     * @return 二进制流
     */
    InputStream getObject(String bucketName, String objectName);

    /**
     * 上传文件
     *
     * @param bucketName bucket名称
     * @param stream     文件流
     * @throws Exception https://docs.minio.io/cn/java-client-api-reference.html#putObject
     */
    void putObject(String bucketName, String objectName, InputStream stream);

    /**
     * 上传文件
     *
     * @param bucketName  bucket名称
     * @param objectName  文件名称
     * @param stream      文件流
     * @param size        大小
     * @param contextType 类型
     * @throws Exception https://docs.minio.io/cn/java-client-api-reference.html#putObject
     */
    void putObject(String bucketName, String objectName, InputStream stream, long size, String contextType);

    /**
     * 获取文件信息, 如果抛出异常则说明文件不存在
     *
     * @param bucketName bucket名称
     * @param objectName 文件名称
     * @throws Exception https://docs.minio.io/cn/java-client-api-reference.html#statObject
     */
    StatObjectResponse getObjectInfo(String bucketName, String objectName);

    /**
     * 删除文件
     *
     * @param bucketName bucket名称
     * @param objectName 文件名称
     * @throws Exception https://docs.minio.io/cn/java-client-api-reference.html#removeObject
     */
    boolean removeObject(String bucketName, String objectName) throws Exception;
}

@Slf4j
@Service
public class UploadFileServiceImpl implements UploadFileService {

    private MinioClient minioClient;

    @Autowired
    MinioConfig minioConfig;

    @PostConstruct
    public void init() {
        this.minioClient =
                MinioClient.builder()
                        .endpoint(minioConfig.getEndpoint())
                        .credentials(minioConfig.getAccessKey(), minioConfig.getSecretKey())
                        .build();
    }

    @Override
    @SneakyThrows
    public void createBucket(String bucketName) {
        if (!minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build())) {
            minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
        }
    }

    @Override
    @SneakyThrows
    public List<Bucket> getAllBuckets() {
        // 列出所有存储桶
        return minioClient.listBuckets();
    }

    @Override
    @SneakyThrows
    public Optional<Bucket> getBucket(String bucketName) {
        return minioClient.listBuckets().stream().filter(b -> b.name().equals(bucketName)).findFirst();
    }

    @Override
    @SneakyThrows
    public void removeBucket(String bucketName) {
        // 删除之前先检查bucketName是否存在。
        boolean found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
        if (found) {
            // 删除bucketName存储桶,注意,只有存储桶为空时才能删除成功。
            minioClient.removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build());
        } else {
            log.info(bucketName + "does not exist");
        }
    }

    @Override
    @SneakyThrows
    public List getAllObjectsByPrefix(String bucketName, String prefix, boolean recursive) {
        List<Item> list = new ArrayList<>();
        Iterable<Result<Item>> objectsIterator = minioClient.listObjects(
                ListObjectsArgs.builder().bucket(bucketName).prefix(prefix)
                        .recursive(recursive).build()
        );
        if (objectsIterator != null) {
            Iterator<Result<Item>> iterator = objectsIterator.iterator();
            if (iterator != null) {
                while (iterator.hasNext()) {
                    Result<Item> result = iterator.next();
                    Item item = result.get();
                    list.add(item);
                }
            }
        }

        return list;
    }

    @Override
    @SneakyThrows
    public String getObjectURL(String bucketName, String objectName, Integer expires) {
        return minioClient.getPresignedObjectUrl(
                GetPresignedObjectUrlArgs.builder()
                        .method(Method.GET)
                        .bucket(bucketName)
                        .object(objectName)
                        .expiry(expires, TimeUnit.DAYS)
                        .build());
    }

    @Override
    @SneakyThrows
    public InputStream getObject(String bucketName, String objectName) {
        return minioClient.getObject(GetObjectArgs.builder()
                .bucket(bucketName)
                .object(objectName)
                .build());
    }

    @Override
    @SneakyThrows
    public void putObject(String bucketName, String objectName, InputStream stream) {
        // 检查存储桶是否已经存在
        if (!minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build())) {
            minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
        }
        minioClient.putObject(
                PutObjectArgs.builder().bucket(bucketName).object(objectName).stream(
                        stream, stream.available(), -1)
                        .build());
    }

    @Override
    @SneakyThrows
    public void putObject(String bucketName, String objectName, InputStream stream, long size, String contextType) {
        minioClient.putObject(
                PutObjectArgs.builder().bucket(bucketName)
                        .object(objectName).stream(stream, size, -1)
                        .contentType(contextType).build());
    }

    @Override
    @SneakyThrows
    public StatObjectResponse getObjectInfo(String bucketName, String objectName) {
        StatObjectResponse statObjectResponse = minioClient.statObject(StatObjectArgs.builder().bucket(bucketName).object(objectName).build());
        return statObjectResponse;
    }

    @Override
    public boolean removeObject(String bucketName, String objectName) throws Exception {
        try {
            minioClient.removeObject(
                    RemoveObjectArgs.builder()
                            .bucket(bucketName)
                            .object(objectName)
                            .build());
        } catch (Exception e) {
            return false;
        }
        return true;
    }
}

7.编写ReportData类
@Slf4j
@Data
@Component
public class ReportData {
//generateReport可加入需要的参数
    public String generateReport() throws IOException, XDocReportException {
        //通过freemarker模板引擎加载文档,并缓存到registry中
        ClassPathResource resource= new ClassPathResource("templates/report.docx");
        InputStream input = resource.getInputStream();
        IXDocReport report = XDocReportRegistry
                .getRegistry()
                .loadReport(input, TemplateEngineKind.Freemarker);

        //匹配填充字段和填充数据,进行填充
        IContext context = report.createContext();
        //获取要放入报告的数据(省略),假设获取到了一个list数组dataList
        

        //context.put(" ", )放入相应的数据,可在word模板中动态调用
        context.put("time", LocalDateTime.now());
        context.put("dataList",dataList);

        ByteArrayOutputStream output = new ByteArrayOutputStream();
        report.process(context, output);
        
        ByteArrayInputStream inputStream = new ByteArrayInputStream(output.toByteArray());
         String objectName = "Document/"+"报告.docx";
        uploadFileService.putObject(minioConfig.getBucketName(),objectName, inputStream);
        return objectName;
    }
}
8.controller层调用
 @RequestMapping(value = "/reportExport", method = RequestMethod.POST)
//UserServiceByReportExport中可填写所需参数
    public void UserServiceByReportExport(HttpServletRequest request, HttpServletResponse response) throws IOException, XDocReportException {
        // TODO 使用预置的word文档导出
        String objectName = reportData.generateReport();
        Optional<InputStream> inputOp = Optional.of(uploadFileService.getObject(minioConfig.getBucketName(), objectName));
        if (!inputOp.isPresent()) {
            throw new NullPointerException("报告生成失败");
        }

        try (InputStream input1 = inputOp.get();
             OutputStream output1 = response.getOutputStream()) {
            response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
            response.addHeader("Content-Disposition",
                    "attachment;filename=" + URLEncoder.encode( "报告.docx", "UTF-8"));
            response.setHeader("Access-Control-Expose-Headers","Content-Disposition");
            IoUtils.copy(input1, output1);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值