Java实现动态生成word报告

news/2025/3/4 13:04:57/

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:9000accessKey: miniosecretKey: minio123bucketName: carbonexpires: 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名称*/// @SneakyThrowsOptional<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;@AutowiredMinioConfig minioConfig;@PostConstructpublic void init() {this.minioClient =MinioClient.builder().endpoint(minioConfig.getEndpoint()).credentials(minioConfig.getAccessKey(), minioConfig.getSecretKey()).build();}@Override@SneakyThrowspublic void createBucket(String bucketName) {if (!minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build())) {minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());}}@Override@SneakyThrowspublic List<Bucket> getAllBuckets() {// 列出所有存储桶return minioClient.listBuckets();}@Override@SneakyThrowspublic Optional<Bucket> getBucket(String bucketName) {return minioClient.listBuckets().stream().filter(b -> b.name().equals(bucketName)).findFirst();}@Override@SneakyThrowspublic 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@SneakyThrowspublic 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@SneakyThrowspublic 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@SneakyThrowspublic InputStream getObject(String bucketName, String objectName) {return minioClient.getObject(GetObjectArgs.builder().bucket(bucketName).object(objectName).build());}@Override@SneakyThrowspublic 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@SneakyThrowspublic 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@SneakyThrowspublic StatObjectResponse getObjectInfo(String bucketName, String objectName) {StatObjectResponse statObjectResponse = minioClient.statObject(StatObjectArgs.builder().bucket(bucketName).object(objectName).build());return statObjectResponse;}@Overridepublic 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();}}

http://www.ppmy.cn/news/421012.html

相关文章

基于Java学生请假系统设计实现(源码+lw+部署文档+讲解等)

博主介绍&#xff1a; ✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战 ✌ &#x1f345; 文末获取源码联系 &#x1f345; &#x1f447;&#x1f3fb; 精…

论论坛现状

随着网路的不断发展&#xff0c;在便利我们的同时&#xff0c;也带来了许多的问题&#xff1a;好的软件一发布出来&#xff0c;那些昧着良心的编程师就篡改其信息发布在别的论坛上&#xff0c;然后“拆东墙补西墙”&#xff0c;既能赚分&#xff0c;又能赚钱。何乐而不为&#…

互联网交流网站

成品详细信息 开发工具(eclipse/idea/vscode等)&#xff1a; 数据库(sqlite/mysql/sqlserver等)&#xff1a; 功能模块(请用文字描述&#xff0c;至少200字)&#xff1a;

世界论坛网

世界论坛网 链接:http://www.wforum.com/cgi-bin/specials/index.cgi?actmain;omilitary 来自 “ ITPUB博客 ” &#xff0c;链接&#xff1a;http://blog.itpub.net/5718/viewspace-168212/&#xff0c;如需转载&#xff0c;请注明出处&#xff0c;否则将追究法律责任。 转载…

中美互联网现状 ​​​​

你在其中哪家呢&#xff1f;&#xff1f;&#xff1f; 推荐阅读&#xff1a; 各大 IT 公司的架构图 程序员不同层次的自由

2022年中美互联网企业研发投入排行

中国信通院《全球数字经济白皮书&#xff08;2022年&#xff09;》提到&#xff0c;2021年发达国家数字经济占GDP比重为55.7%&#xff0c;远超发展中国家29.8%的水平。从增速看&#xff0c;发展中国家数字经济同比名义增长22.3%&#xff0c;高于同期发达国家数字经济增速9.1个百…

2020中国互联网大会|数据中心论坛要来了

今年&#xff0c;数据中心妥妥地站上了“新基建”C位&#xff0c;数据中心作为“新基建”的重要基石&#xff0c;加快推进产业发展&#xff0c;将为整个社会的数字化、网络化、智能化发展注入强劲动力。在“新基建”为数据中心发展注入了新的强劲动力的同时&#xff0c;也对数据…

中国IT论坛排名

1. csdncsdn 的注册人数多(号称过两百万的用户) ,但新手多.2. java eyejava eye 注册用户刚突破 10 万,但更为专业. (附 CSDN 与 JavaEye 博客和论坛的比较)3. infoQwww.apusic.cominfoQ相对来说是比较新的技术,新概念.4. 编程爱好者网站 www.programfan.com提供各种流行语言的…