Java实现动态生成word报告

Java实现动态生成word报告

1.准备好docx文件模板

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

Java实现动态生成word报告_第1张图片

将写好的word模板加入到templates目录下
Java实现动态生成word报告_第2张图片

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
     * 

* 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();
        }
    }

你可能感兴趣的:(java,word,开发语言)