├── .gitignore
├── README.md
├── README_EN.md
├── pom.xml
└── src
└── main
└── java
└── cn
└── veasion
└── aippt
├── AiPptDemo1.java
├── AiPptDemo2.java
├── AiPptDemo3.java
├── AiPptDemo4.java
├── Api.java
└── HttpUtils.java
/.gitignore:
--------------------------------------------------------------------------------
1 | target/
2 | !.mvn/wrapper/maven-wrapper.jar
3 | !**/src/main/**/target/
4 | !**/src/test/**/target/
5 |
6 | ### IntelliJ IDEA ###
7 | .idea/
8 | *.iws
9 | *.iml
10 | *.ipr
11 |
12 | ### Eclipse ###
13 | .apt_generated
14 | .classpath
15 | .factorypath
16 | .project
17 | .settings
18 | .springBeans
19 | .sts4-cache
20 |
21 | ### NetBeans ###
22 | /nbproject/private/
23 | /nbbuild/
24 | /dist/
25 | /nbdist/
26 | /.nb-gradle/
27 | build/
28 | !**/src/main/**/build/
29 | !**/src/test/**/build/
30 |
31 | ### VS Code ###
32 | .vscode/
33 |
34 | ### Mac OS ###
35 | .DS_Store
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |

2 | 文多多 AiPPT
3 |
4 | 简体中文 | English
5 |
6 |
7 | 🔗在线演示
8 | •
9 | 📝PPT转JSON
10 | •
11 | 🌏官方网站
12 | •
13 | 💬合作交流
14 |
15 |
16 |
17 |
18 |
19 |
20 | # 🤖 AI 生成 PPT
21 |
22 | 商用级 AI 生成 PPT 项目,包含以下功能:
23 |
24 | * AI 生成 PPT
25 | * PPT 解析成 JSON
26 | * JSON 反渲染为 PPT
27 |
28 |
29 |
30 | # ✨ AiPPT
31 |
32 | 在线体验:https://veasion.github.io/aippt
33 |
34 |
35 | [演示视频](https://metasign-public.oss-cn-shanghai.aliyuncs.com/github/aippt.mp4)
36 |
37 | https://github.com/veasion/aippt/assets/24989778/24d5654b-09f3-4554-a732-dbffc1073a1d
38 |
39 |
40 |
41 | # ✨ PPT 解析成 JSON
42 |
43 | 支持上传PPT并渲染,在线编辑,编辑后下载 ppt 文件。
44 |
45 | 在线体验:https://veasion.github.io/aippt/ppt2json.html
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 | # 🤝 商业合作
55 |
56 | 针对上面技术,我们开发了一套可商用 aippt 软件,支持代理 & 私有化部署!
57 |
58 | 我们的优势,支持定制化行业解决方案,支持原生图表、动画等复杂PPT解析和渲染,支持用户自定义模板,技术方案行业领先,价格行业最低。
59 |
60 | 官网地址(开放API):
61 | https://docmee.cn
62 |
63 | 开放平台(API/UI 接入):
64 | https://docmee.cn/open-platform
65 |
66 |
67 | 商业合作 & 进群交流:
68 |
69 | 
70 |
--------------------------------------------------------------------------------
/README_EN.md:
--------------------------------------------------------------------------------
1 | 
2 | Docmee AiPPT
3 |
4 | English | 简体中文
5 |
6 |
7 | 🔗Demo
8 | •
9 | 📝PPT to JSON
10 | •
11 | 🌏Official website
12 | •
13 | 💬Business cooperation
14 |
15 |
16 |
17 |
18 |
19 |
20 | # 🤖 AI Generate PPT
21 |
22 | Commercial level AI generated PPT project, including the following features:
23 |
24 | * AI generated PPT
25 | * PPT parsed into JSON
26 | * JSON re-rendered as PPT
27 |
28 |
29 |
30 | # ✨ AiPPT
31 |
32 | Demo: https://veasion.github.io/aippt
33 |
34 | [Demo Video](https://metasign-public.oss-cn-shanghai.aliyuncs.com/github/aippt.mp4)
35 |
36 | https://github.com/veasion/aippt/assets/24989778/24d5654b-09f3-4554-a732-dbffc1073a1d
37 |
38 |
39 |
40 | # ✨ PPT to JSON
41 |
42 | Support uploading PPT and rendering, online editing, and download the edited PPT file.
43 |
44 | Demo: https://veasion.github.io/aippt/ppt2json.html
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 | # 🤝 Business cooperation
54 |
55 | We have developed a commercially available aippt software that supports proxy and private deployment for the above technology!
56 |
57 | Our advantages include supporting customized industry solutions, supporting complex PPT analysis and rendering such as native charts and animations, supporting user-defined templates, leading technology solutions, and the lowest prices in the industry.
58 |
59 | Official website (Open API):
60 | https://docmee.cn
61 |
62 | Open platform (API / UI):
63 | https://docmee.cn/open-platform
64 |
65 |
66 | WeChat group qrcode:
67 |
68 | 
69 |
70 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | cn.veasion
8 | aippt-api-java-demo
9 | 1.0.0
10 |
11 |
12 | 1.8
13 | 8
14 | 8
15 | UTF-8
16 | UTF-8
17 | 1.2.83
18 | 2.15.0
19 | 4.5.14
20 |
21 |
22 |
23 |
24 |
25 | com.alibaba
26 | fastjson
27 | ${fastjson.version}
28 |
29 |
30 |
31 | org.apache.httpcomponents
32 | httpmime
33 | ${httpclient.version}
34 |
35 |
36 | commons-io
37 | commons-io
38 | ${commons-io.version}
39 |
40 |
41 |
42 |
43 |
44 |
45 | src/main/java
46 |
47 |
48 |
49 |
50 | org.apache.maven.plugins
51 | maven-compiler-plugin
52 | 3.1
53 |
54 | 1.8
55 | 1.8
56 |
57 |
58 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/src/main/java/cn/veasion/aippt/AiPptDemo1.java:
--------------------------------------------------------------------------------
1 | package cn.veasion.aippt;
2 |
3 | import com.alibaba.fastjson.JSONObject;
4 |
5 | import javax.swing.filechooser.FileSystemView;
6 | import java.io.File;
7 |
8 | /**
9 | * 同步流式生成 PPT
10 | *
11 | * @author veasion
12 | * @date 2024/7/12
13 | */
14 | public class AiPptDemo1 {
15 |
16 | public static void main(String[] args) throws Exception {
17 | // 官网 https://docmee.cn
18 | // 开放平台 https://docmee.cn/open-platform/api
19 |
20 | // 填写你的API-KEY
21 | String apiKey = "YOUR API KEY";
22 |
23 | // 第三方用户ID(数据隔离)
24 | String uid = "test";
25 | String subject = "AI未来的发展";
26 |
27 | // 创建 api token (有效期2小时,建议缓存到redis,同一个 uid 创建时之前的 token 会在10秒内失效)
28 | String apiToken = Api.createApiToken(apiKey, uid, null);
29 | System.out.println("api token: " + apiToken);
30 |
31 | // 生成大纲
32 | System.out.println("\n\n========== 正在生成大纲 ==========");
33 | String outline = Api.generateOutline(apiToken, subject, null, null);
34 |
35 | // 生成大纲内容
36 | System.out.println("\n\n========== 正在生成大纲内容 ==========");
37 | String markdown = Api.generateContent(apiToken, outline, null, null);
38 |
39 | // 随机一个模板
40 | System.out.println("\n\n========== 随机选择模板 ==========");
41 | String templateId = Api.randomOneTemplateId(apiToken);
42 | System.out.println(templateId);
43 |
44 | // 生成PPT
45 | System.out.println("\n\n========== 正在生成PPT ==========");
46 | JSONObject pptInfo = Api.generatePptx(apiToken, templateId, markdown, false);
47 | String pptId = pptInfo.getString("id");
48 | System.out.println("pptId: " + pptId);
49 | System.out.println("ppt主题:" + pptInfo.getString("subject"));
50 | System.out.println("ppt封面:" + pptInfo.getString("coverUrl") + "?token=" + apiToken);
51 |
52 | // 下载PPT到桌面
53 | System.out.println("\n\n========== 正在下载PPT ==========");
54 | JSONObject result = Api.downloadPptx(apiToken, pptId);
55 | String url = result.getString("fileUrl");
56 | System.out.println("ppt链接:" + url);
57 | String savePath = FileSystemView.getFileSystemView().getHomeDirectory().getAbsolutePath() + File.separator + pptId + ".pptx";
58 | HttpUtils.download(url, new File(savePath));
59 | System.out.println("ppt下载完成,保存路径:" + savePath);
60 | }
61 |
62 | }
63 |
--------------------------------------------------------------------------------
/src/main/java/cn/veasion/aippt/AiPptDemo2.java:
--------------------------------------------------------------------------------
1 | package cn.veasion.aippt;
2 |
3 | import com.alibaba.fastjson.JSONObject;
4 |
5 | import javax.swing.filechooser.FileSystemView;
6 | import java.io.File;
7 | import java.util.Map;
8 |
9 | /**
10 | * 异步流式生成 PPT
11 | *
12 | * @author veasion
13 | * @date 2024/7/12
14 | */
15 | public class AiPptDemo2 {
16 |
17 | public static void main(String[] args) throws Exception {
18 | // 官网 https://docmee.cn
19 | // 开放平台 https://docmee.cn/open-platform/api
20 |
21 | // 填写你的API-KEY
22 | String apiKey = "YOUR API KEY";
23 |
24 | // 第三方用户ID(数据隔离)
25 | String uid = "test";
26 | // 文档文件,支持 word/excel/ppt/md/txt/pdf 等类型
27 | File file = new File("README.md");
28 |
29 | // 创建 api token (有效期2小时,建议缓存到redis,同一个 uid 创建时之前的 token 会在10秒内失效)
30 | String apiToken = Api.createApiToken(apiKey, uid, null);
31 | System.out.println("apiToken: " + apiToken);
32 |
33 | // 解析文件
34 | String dataUrl = Api.parseFileData(apiToken, file, null, null);
35 |
36 | // 生成大纲
37 | System.out.println("\n\n========== 正在生成大纲 ==========");
38 | String outline = Api.generateOutline(apiToken, null, dataUrl, null);
39 |
40 | // 异步生成大纲内容
41 | System.out.println("\n\n========== 正在异步生成大纲内容 ==========");
42 | Map pptInfo = Api.asyncGenerateContent(apiToken, outline, dataUrl, null, null);
43 |
44 | String pptId = pptInfo.get("id");
45 |
46 | // 下载PPT到桌面
47 | System.out.println("\n\n========== 正在下载PPT ==========");
48 | System.out.println("pptId: " + pptId);
49 | String url = null;
50 | for (int i = 0; i < 30; i++) {
51 | // 等待PPT文件可下载
52 | JSONObject result = Api.downloadPptx(apiToken, pptId);
53 | if (result != null) {
54 | url = result.getString("fileUrl");
55 | if (url != null) {
56 | break;
57 | }
58 | }
59 | Thread.sleep(1000);
60 | }
61 | System.out.println("ppt链接:" + url);
62 | String savePath = FileSystemView.getFileSystemView().getHomeDirectory().getAbsolutePath() + File.separator + pptId + ".pptx";
63 | HttpUtils.download(url, new File(savePath));
64 | System.out.println("ppt下载完成,保存路径:" + savePath);
65 | }
66 |
67 | }
68 |
--------------------------------------------------------------------------------
/src/main/java/cn/veasion/aippt/AiPptDemo3.java:
--------------------------------------------------------------------------------
1 | package cn.veasion.aippt;
2 |
3 | import com.alibaba.fastjson.JSONObject;
4 |
5 | import javax.swing.filechooser.FileSystemView;
6 | import java.io.File;
7 |
8 | /**
9 | * 通过主题直接生成 PPT
10 | *
11 | * @author veasion
12 | * @date 2024/7/12
13 | */
14 | public class AiPptDemo3 {
15 |
16 | public static void main(String[] args) throws Exception {
17 | // 官网 https://docmee.cn
18 | // 开放平台 https://docmee.cn/open-platform/api
19 |
20 | // 填写你的API-KEY
21 | String apiKey = "YOUR API KEY";
22 |
23 | // 第三方用户ID(数据隔离)
24 | String uid = "test";
25 | String subject = "AI未来的发展";
26 |
27 | // 创建 api token (有效期2小时,建议缓存到redis,同一个 uid 创建时之前的 token 会在10秒内失效)
28 | String apiToken = Api.createApiToken(apiKey, uid, null);
29 | System.out.println("apiToken: " + apiToken);
30 |
31 | // 通过主题直接生成PPT
32 | System.out.println("\n正在生成PPT...\n");
33 | JSONObject pptInfo = Api.directGeneratePptx(apiToken, true, null, subject, null, null, false);
34 |
35 | String pptId = pptInfo.getString("id");
36 | String fileUrl = pptInfo.getString("fileUrl");
37 | System.out.println("\n\n===============");
38 | System.out.println("pptId: " + pptId);
39 | System.out.println("ppt主题:" + pptInfo.getString("subject"));
40 | System.out.println("ppt封面:" + pptInfo.getString("coverUrl"));
41 | System.out.println("ppt链接:" + fileUrl);
42 |
43 | // 下载PPT到桌面
44 | String savePath = FileSystemView.getFileSystemView().getHomeDirectory().getAbsolutePath() + File.separator + pptId + ".pptx";
45 | HttpUtils.download(fileUrl, new File(savePath));
46 | System.out.println("ppt下载完成,保存路径:" + savePath);
47 | }
48 |
49 | }
50 |
--------------------------------------------------------------------------------
/src/main/java/cn/veasion/aippt/AiPptDemo4.java:
--------------------------------------------------------------------------------
1 | package cn.veasion.aippt;
2 |
3 | import com.alibaba.fastjson.JSONObject;
4 |
5 | import javax.swing.filechooser.FileSystemView;
6 | import java.io.File;
7 |
8 | /**
9 | * 通过文件直接生成 PPT
10 | *
11 | * @author veasion
12 | * @date 2024/7/12
13 | */
14 | public class AiPptDemo4 {
15 |
16 | public static void main(String[] args) throws Exception {
17 | // 官网 https://docmee.cn
18 | // 开放平台 https://docmee.cn/open-platform/api
19 |
20 | // 填写你的API-KEY
21 | String apiKey = "YOUR API KEY";
22 |
23 | // 第三方用户ID(数据隔离)
24 | String uid = "test";
25 | // 文档文件,支持 word/excel/ppt/md/txt/pdf 等类型
26 | File file = new File("README.md");
27 |
28 | // 创建 api token (有效期2小时,建议缓存到redis,同一个 uid 创建时之前的 token 会在10秒内失效)
29 | String apiToken = Api.createApiToken(apiKey, uid, null);
30 | System.out.println("apiToken: " + apiToken);
31 |
32 | // 解析文件
33 | String dataUrl = Api.parseFileData(apiToken, file, null, null);
34 |
35 | // 通过文件直接生成PPT
36 | System.out.println("\n正在生成PPT...\n");
37 | JSONObject pptInfo = Api.directGeneratePptx(apiToken, true, null, null, dataUrl, null, false);
38 |
39 | String pptId = pptInfo.getString("id");
40 | String fileUrl = pptInfo.getString("fileUrl");
41 | System.out.println("\n\n===============");
42 | System.out.println("pptId: " + pptId);
43 | System.out.println("ppt主题:" + pptInfo.getString("subject"));
44 | System.out.println("ppt封面:" + pptInfo.getString("coverUrl"));
45 | System.out.println("ppt链接:" + fileUrl);
46 |
47 | // 下载PPT到桌面
48 | String savePath = FileSystemView.getFileSystemView().getHomeDirectory().getAbsolutePath() + File.separator + pptId + ".pptx";
49 | HttpUtils.download(fileUrl, new File(savePath));
50 | System.out.println("ppt下载完成,保存路径:" + savePath);
51 | }
52 |
53 | }
54 |
--------------------------------------------------------------------------------
/src/main/java/cn/veasion/aippt/Api.java:
--------------------------------------------------------------------------------
1 | package cn.veasion.aippt;
2 |
3 | import com.alibaba.fastjson.JSONArray;
4 | import com.alibaba.fastjson.JSONObject;
5 | import org.apache.http.entity.ContentType;
6 | import org.apache.http.entity.mime.MultipartEntityBuilder;
7 |
8 | import java.io.File;
9 | import java.nio.charset.StandardCharsets;
10 | import java.util.HashMap;
11 | import java.util.Map;
12 | import java.util.Objects;
13 |
14 | /**
15 | * Api
16 | *
17 | * @author luozhuowei
18 | * @date 2024/7/15
19 | */
20 | public class Api {
21 |
22 | public static final String BASE_URL = "https://docmee.cn";
23 |
24 | public static String createApiToken(String apiKey, String uid, Integer limit) {
25 | String url = BASE_URL + "/api/user/createApiToken";
26 | JSONObject body = new JSONObject();
27 | body.put("uid", uid);
28 | body.put("limit", limit);
29 | HttpUtils.HttpRequest httpRequest = HttpUtils.HttpRequest.postJson(url);
30 | httpRequest.setBody(body.toJSONString());
31 | httpRequest.addHeaders("Api-Key", apiKey);
32 | HttpUtils.HttpResponse response = HttpUtils.request(httpRequest);
33 | if (response.getStatus() != 200) {
34 | throw new RuntimeException("创建apiToken失败,httpStatus=" + response.getStatus());
35 | }
36 | JSONObject result = response.getResponseToJson();
37 | if (result.getIntValue("code") != 0) {
38 | throw new RuntimeException("创建apiToken异常," + result.getString("message"));
39 | }
40 | return result.getJSONObject("data").getString("token");
41 | }
42 |
43 | public static String parseFileData(String apiToken, File file, String content, String fileUrl) {
44 | String url = BASE_URL + "/api/ppt/parseFileData";
45 | HttpUtils.HttpRequest httpRequest = new HttpUtils.HttpRequest();
46 | httpRequest.setUrl(url);
47 | httpRequest.setMethod("POST");
48 | httpRequest.addHeaders("token", apiToken);
49 | MultipartEntityBuilder multipartEntity = MultipartEntityBuilder.create();
50 | multipartEntity.setCharset(StandardCharsets.UTF_8);
51 | if (file != null) {
52 | multipartEntity.addBinaryBody("file", file);
53 | }
54 | if (content != null) {
55 | multipartEntity.addTextBody("content", content, ContentType.create("text/plain", StandardCharsets.UTF_8));
56 | }
57 | if (fileUrl != null) {
58 | multipartEntity.addTextBody("fileUrl", fileUrl, ContentType.create("text/plain", StandardCharsets.UTF_8));
59 | }
60 | httpRequest.setBody(multipartEntity.build());
61 | HttpUtils.HttpResponse response = HttpUtils.request(httpRequest);
62 | if (response.getStatus() != 200) {
63 | throw new RuntimeException("解析文件或内容失败,httpStatus=" + response.getStatus());
64 | }
65 | JSONObject result = response.getResponseToJson();
66 | if (result.getIntValue("code") != 0) {
67 | throw new RuntimeException("解析文件或内容异常," + result.getString("message"));
68 | }
69 | return result.getJSONObject("data").getString("dataUrl");
70 | }
71 |
72 | public static String generateOutline(String apiToken, String subject, String dataUrl, String prompt) {
73 | String url = BASE_URL + "/api/ppt/generateOutline";
74 | JSONObject body = new JSONObject();
75 | body.put("subject", subject);
76 | body.put("dataUrl", dataUrl);
77 | body.put("prompt", prompt);
78 | HttpUtils.HttpRequest httpRequest = HttpUtils.HttpRequest.postJson(url);
79 | httpRequest.setBody(body.toJSONString());
80 | httpRequest.addHeaders("token", apiToken);
81 | StringBuilder sb = new StringBuilder();
82 | HttpUtils.HttpResponse response = HttpUtils.requestWithEventStream(httpRequest, data -> {
83 | if (data == null || data.isEmpty()) {
84 | return;
85 | }
86 | JSONObject json = JSONObject.parseObject(data);
87 | if (Objects.equals(json.getInteger("status"), -1)) {
88 | throw new RuntimeException(json.getString("error"));
89 | }
90 | String text = json.getString("text");
91 | sb.append(text);
92 | // 打印输出
93 | System.out.print(text);
94 | });
95 | if (response.getStatus() != 200) {
96 | throw new RuntimeException("生成大纲失败,httpStatus=" + response.getStatus());
97 | }
98 | if (response.getHeaders().getOrDefault("Content-Type", response.getHeaders().get("content-type")).contains("application/json")) {
99 | JSONObject result = response.getResponseToJson();
100 | throw new RuntimeException("生成大纲失败:" + result.getString("message"));
101 | }
102 | return sb.toString();
103 | }
104 |
105 | public static String generateContent(String apiToken, String outlineMarkdown, String dataUrl, String prompt) {
106 | String url = BASE_URL + "/api/ppt/generateContent";
107 | JSONObject body = new JSONObject();
108 | body.put("outlineMarkdown", outlineMarkdown);
109 | body.put("dataUrl", dataUrl);
110 | body.put("prompt", prompt);
111 | HttpUtils.HttpRequest httpRequest = HttpUtils.HttpRequest.postJson(url);
112 | httpRequest.setBody(body.toJSONString());
113 | httpRequest.addHeaders("token", apiToken);
114 | StringBuilder sb = new StringBuilder();
115 | HttpUtils.HttpResponse response = HttpUtils.requestWithEventStream(httpRequest, data -> {
116 | if (data == null || data.isEmpty()) {
117 | return;
118 | }
119 | JSONObject json = JSONObject.parseObject(data);
120 | if (Objects.equals(json.getInteger("status"), -1)) {
121 | throw new RuntimeException(json.getString("error"));
122 | }
123 | String text = json.getString("text");
124 | sb.append(text);
125 | // 打印输出
126 | System.out.print(text);
127 | });
128 | if (response.getStatus() != 200) {
129 | throw new RuntimeException("生成大纲内容失败,httpStatus=" + response.getStatus());
130 | }
131 | if (response.getHeaders().getOrDefault("Content-Type", response.getHeaders().get("content-type")).contains("application/json")) {
132 | JSONObject result = response.getResponseToJson();
133 | throw new RuntimeException("生成大纲内容失败:" + result.getString("message"));
134 | }
135 | return sb.toString();
136 | }
137 |
138 | public static Map asyncGenerateContent(String apiToken, String outlineMarkdown, String dataUrl, String templateId, String prompt) {
139 | String url = BASE_URL + "/api/ppt/generateContent";
140 | JSONObject body = new JSONObject();
141 | body.put("asyncGenPptx", true);
142 | body.put("templateId", templateId);
143 | body.put("outlineMarkdown", outlineMarkdown);
144 | body.put("dataUrl", dataUrl);
145 | body.put("prompt", prompt);
146 | HttpUtils.HttpRequest httpRequest = HttpUtils.HttpRequest.postJson(url);
147 | httpRequest.setBody(body.toJSONString());
148 | httpRequest.addHeaders("token", apiToken);
149 | Map pptInfo = new HashMap<>();
150 | StringBuilder sb = new StringBuilder();
151 | HttpUtils.HttpResponse response = HttpUtils.requestWithEventStream(httpRequest, data -> {
152 | if (data == null || data.isEmpty()) {
153 | return;
154 | }
155 | JSONObject json = JSONObject.parseObject(data);
156 | if (Objects.equals(json.getInteger("status"), -1)) {
157 | throw new RuntimeException(json.getString("error"));
158 | }
159 | if (json.getString("pptId") != null) {
160 | pptInfo.put("id", json.getString("pptId"));
161 | }
162 | String text = json.getString("text");
163 | sb.append(text);
164 | // 打印输出
165 | System.out.print(text);
166 | });
167 | if (response.getStatus() != 200) {
168 | throw new RuntimeException("生成大纲内容失败,httpStatus=" + response.getStatus());
169 | }
170 | if (response.getHeaders().getOrDefault("Content-Type", response.getHeaders().get("content-type")).contains("application/json")) {
171 | JSONObject result = response.getResponseToJson();
172 | throw new RuntimeException("生成大纲内容失败:" + result.getString("message"));
173 | }
174 | pptInfo.put("markdown", sb.toString());
175 | return pptInfo;
176 | }
177 |
178 | public static String randomOneTemplateId(String apiToken) {
179 | String url = BASE_URL + "/api/ppt/randomTemplates";
180 | JSONObject body = new JSONObject();
181 | body.put("size", 1);
182 | JSONObject filters = new JSONObject();
183 | filters.put("type", 1);
184 | body.put("filters", filters);
185 | HttpUtils.HttpRequest httpRequest = HttpUtils.HttpRequest.postJson(url);
186 | httpRequest.setBody(body.toJSONString());
187 | httpRequest.addHeaders("token", apiToken);
188 | HttpUtils.HttpResponse response = HttpUtils.request(httpRequest);
189 | if (response.getStatus() != 200) {
190 | throw new RuntimeException("获取模板失败,httpStatus=" + response.getStatus());
191 | }
192 | JSONObject result = response.getResponseToJson();
193 | if (result.getIntValue("code") != 0) {
194 | throw new RuntimeException("获取模板异常," + result.getString("message"));
195 | }
196 | JSONArray data = result.getJSONArray("data");
197 | JSONObject template = data.getJSONObject(0);
198 | return template.getString("id");
199 | }
200 |
201 | public static JSONObject generatePptx(String apiToken, String templateId, String markdown, boolean pptxProperty) {
202 | String url = BASE_URL + "/api/ppt/generatePptx";
203 | JSONObject body = new JSONObject();
204 | body.put("templateId", templateId);
205 | body.put("outlineContentMarkdown", markdown);
206 | body.put("pptxProperty", pptxProperty);
207 | HttpUtils.HttpRequest httpRequest = HttpUtils.HttpRequest.postJson(url);
208 | httpRequest.setBody(body.toJSONString());
209 | httpRequest.addHeaders("token", apiToken);
210 | HttpUtils.HttpResponse response = HttpUtils.request(httpRequest);
211 | if (response.getStatus() != 200) {
212 | throw new RuntimeException("生成PPT失败,httpStatus=" + response.getStatus());
213 | }
214 | JSONObject result = response.getResponseToJson();
215 | if (result.getIntValue("code") != 0) {
216 | throw new RuntimeException("生成PPT异常," + result.getString("message"));
217 | }
218 | return result.getJSONObject("data").getJSONObject("pptInfo");
219 | }
220 |
221 | public static JSONObject downloadPptx(String apiToken, String id) {
222 | String url = BASE_URL + "/api/ppt/downloadPptx";
223 | JSONObject body = new JSONObject();
224 | body.put("id", id);
225 | HttpUtils.HttpRequest httpRequest = HttpUtils.HttpRequest.postJson(url);
226 | httpRequest.setBody(body.toJSONString());
227 | httpRequest.addHeaders("token", apiToken);
228 | HttpUtils.HttpResponse response = HttpUtils.request(httpRequest);
229 | if (response.getStatus() != 200) {
230 | throw new RuntimeException("下载PPT失败,httpStatus=" + response.getStatus());
231 | }
232 | JSONObject result = response.getResponseToJson();
233 | if (result.getIntValue("code") != 0) {
234 | throw new RuntimeException("下载PPT异常," + result.getString("message"));
235 | }
236 | return result.getJSONObject("data");
237 | }
238 |
239 | public static JSONObject directGeneratePptx(String apiToken, boolean stream, String templateId, String subject, String dataUrl, String prompt, boolean pptxProperty) {
240 | String url = BASE_URL + "/api/ppt/directGeneratePptx";
241 | JSONObject body = new JSONObject();
242 | body.put("stream", stream);
243 | body.put("templateId", templateId);
244 | body.put("subject", subject);
245 | body.put("dataUrl", dataUrl);
246 | body.put("prompt", prompt);
247 | body.put("pptxProperty", pptxProperty);
248 | HttpUtils.HttpRequest httpRequest = HttpUtils.HttpRequest.postJson(url);
249 | httpRequest.setBody(body.toJSONString());
250 | httpRequest.addHeaders("token", apiToken);
251 | if (stream) {
252 | // 流式生成
253 | JSONObject[] pptInfo = new JSONObject[1];
254 | HttpUtils.HttpResponse response = HttpUtils.requestWithEventStream(httpRequest, data -> {
255 | if (data == null || data.isEmpty()) {
256 | return;
257 | }
258 | JSONObject json = JSONObject.parseObject(data);
259 | if (Objects.equals(json.getInteger("status"), -1)) {
260 | throw new RuntimeException(json.getString("error"));
261 | }
262 | if (Objects.equals(json.getInteger("status"), 4) && json.containsKey("result")) {
263 | pptInfo[0] = json.getJSONObject("result");
264 | }
265 | String text = json.getString("text");
266 | // 打印输出
267 | System.out.print(text);
268 | });
269 | if (response.getStatus() != 200) {
270 | throw new RuntimeException("生成PPT失败,httpStatus=" + response.getStatus());
271 | }
272 | if (response.getHeaders().getOrDefault("Content-Type", response.getHeaders().get("content-type")).contains("application/json")) {
273 | JSONObject result = response.getResponseToJson();
274 | throw new RuntimeException("生成PPT失败:" + result.getString("message"));
275 | }
276 | return pptInfo[0];
277 | } else {
278 | // 非流式生成
279 | HttpUtils.HttpResponse response = HttpUtils.request(httpRequest);
280 | if (response.getStatus() != 200) {
281 | throw new RuntimeException("生成PPT失败,httpStatus=" + response.getStatus());
282 | }
283 | JSONObject result = response.getResponseToJson();
284 | if (result.getIntValue("code") != 0) {
285 | throw new RuntimeException("生成PPT异常," + result.getString("message"));
286 | }
287 | return result.getJSONObject("data").getJSONObject("pptInfo");
288 | }
289 | }
290 |
291 | }
292 |
--------------------------------------------------------------------------------
/src/main/java/cn/veasion/aippt/HttpUtils.java:
--------------------------------------------------------------------------------
1 | package cn.veasion.aippt;
2 |
3 | import com.alibaba.fastjson.JSON;
4 | import com.alibaba.fastjson.JSONObject;
5 | import org.apache.commons.io.IOUtils;
6 | import org.apache.http.Header;
7 | import org.apache.http.HttpEntity;
8 | import org.apache.http.HttpEntityEnclosingRequest;
9 | import org.apache.http.client.HttpClient;
10 | import org.apache.http.client.config.RequestConfig;
11 | import org.apache.http.client.methods.HttpDelete;
12 | import org.apache.http.client.methods.HttpGet;
13 | import org.apache.http.client.methods.HttpPatch;
14 | import org.apache.http.client.methods.HttpPost;
15 | import org.apache.http.client.methods.HttpPut;
16 | import org.apache.http.client.methods.HttpRequestBase;
17 | import org.apache.http.config.Registry;
18 | import org.apache.http.config.RegistryBuilder;
19 | import org.apache.http.conn.socket.ConnectionSocketFactory;
20 | import org.apache.http.conn.socket.PlainConnectionSocketFactory;
21 | import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
22 | import org.apache.http.entity.ByteArrayEntity;
23 | import org.apache.http.entity.ContentType;
24 | import org.apache.http.entity.FileEntity;
25 | import org.apache.http.entity.InputStreamEntity;
26 | import org.apache.http.entity.StringEntity;
27 | import org.apache.http.impl.client.HttpClients;
28 | import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
29 |
30 | import javax.net.ssl.SSLContext;
31 | import javax.net.ssl.X509TrustManager;
32 | import java.io.BufferedReader;
33 | import java.io.File;
34 | import java.io.FileOutputStream;
35 | import java.io.InputStream;
36 | import java.io.InputStreamReader;
37 | import java.io.Serializable;
38 | import java.io.UnsupportedEncodingException;
39 | import java.net.HttpURLConnection;
40 | import java.net.SocketException;
41 | import java.net.URL;
42 | import java.net.URLEncoder;
43 | import java.nio.charset.StandardCharsets;
44 | import java.security.SecureRandom;
45 | import java.security.cert.X509Certificate;
46 | import java.util.ArrayList;
47 | import java.util.Arrays;
48 | import java.util.Collections;
49 | import java.util.HashMap;
50 | import java.util.LinkedHashMap;
51 | import java.util.List;
52 | import java.util.Map;
53 | import java.util.concurrent.ExecutionException;
54 | import java.util.concurrent.ExecutorService;
55 | import java.util.concurrent.Future;
56 | import java.util.concurrent.TimeUnit;
57 | import java.util.concurrent.TimeoutException;
58 | import java.util.concurrent.atomic.AtomicInteger;
59 | import java.util.function.Consumer;
60 | import java.util.function.Function;
61 |
62 | /**
63 | * HttpUtils
64 | *
65 | * @author veasion
66 | * @date 2021/9/13
67 | */
68 | public class HttpUtils {
69 |
70 | public static final String CHARSET_DEFAULT = "UTF-8";
71 | public static final String CONTENT_TYPE = "Content-Type";
72 | public static final String CONTENT_TYPE_JSON = "application/json";
73 | public static final String CONTENT_TYPE_FORM_DATA = "application/x-www-form-urlencoded";
74 | private static final PoolingHttpClientConnectionManager CONNECTION_MANAGER;
75 | private static final int MAX_CONNECT_TIMEOUT = 8000;
76 | private static final int MAX_SOCKET_TIMEOUT = 90000;
77 |
78 | static {
79 | CONNECTION_MANAGER = new PoolingHttpClientConnectionManager(getDefaultRegistry());
80 | CONNECTION_MANAGER.setMaxTotal(500);
81 | CONNECTION_MANAGER.setDefaultMaxPerRoute(50);
82 | CONNECTION_MANAGER.setValidateAfterInactivity(2000);
83 | }
84 |
85 | public static HttpResponse get(String url) {
86 | return get(url, null);
87 | }
88 |
89 | public static HttpResponse get(String url, Map params) {
90 | String urlLinks = getUrlLinks(params);
91 | if (urlLinks != null) {
92 | if (url.contains("?")) {
93 | url = url + "&" + urlLinks;
94 | } else {
95 | url = url + "?" + urlLinks;
96 | }
97 | }
98 | return request(HttpRequest.build(url, "GET"));
99 | }
100 |
101 | public static void download(String url, File destFile) throws Exception {
102 | HttpRequest request = HttpRequest.build(url, "GET");
103 | request.setResponseHandler(entity -> {
104 | try {
105 | if (!destFile.getParentFile().exists()) {
106 | destFile.getParentFile().mkdirs();
107 | }
108 | try (FileOutputStream fs = new FileOutputStream(destFile)) {
109 | entity.writeTo(fs);
110 | }
111 | return destFile;
112 | } catch (Exception e) {
113 | return e;
114 | }
115 | });
116 | HttpResponse response = request(request);
117 | if (response.getResponse() instanceof Exception) {
118 | throw (Exception) response.getResponse();
119 | }
120 | }
121 |
122 | public static HttpResponse postJson(String url, String bodyJson) {
123 | HttpRequest request = HttpRequest.build(url, "POST").setBody(bodyJson);
124 | if (request.getHeaders() == null) {
125 | request.setHeaders(Collections.singletonMap(CONTENT_TYPE, CONTENT_TYPE_JSON));
126 | } else {
127 | request.getHeaders().put(CONTENT_TYPE, CONTENT_TYPE_JSON);
128 | }
129 | return request(request);
130 | }
131 |
132 | public static HttpResponse postForm(String url, Map params) {
133 | String urlLinks = getUrlLinks(params);
134 | HttpRequest request = HttpRequest.build(url, "POST").setBody(urlLinks != null ? urlLinks : "");
135 | if (request.getHeaders() == null) {
136 | request.setHeaders(Collections.singletonMap(CONTENT_TYPE, CONTENT_TYPE_FORM_DATA));
137 | } else {
138 | request.getHeaders().put(CONTENT_TYPE, CONTENT_TYPE_FORM_DATA);
139 | }
140 | return request(request);
141 | }
142 |
143 | public static HttpResponse requestWithEventStream(ExecutorService executorService, long firstReadTimeout, HttpRequest request, Consumer dataConsumer) throws ExecutionException, InterruptedException, TimeoutException {
144 | return requestWithEventStream(executorService, firstReadTimeout, request, dataConsumer, null);
145 | }
146 |
147 | public static HttpResponse requestWithEventStream(ExecutorService executorService, long firstReadTimeout, HttpRequest request, Consumer dataConsumer, Consumer> futureConsumer) throws ExecutionException, InterruptedException, TimeoutException {
148 | // status: 0 start 1 run 2 timeout
149 | AtomicInteger status = new AtomicInteger(0);
150 | Future submit = executorService.submit(() -> {
151 | if (request.getMaxSocketTimeout() == null) {
152 | request.setMaxSocketTimeout(30_000);
153 | }
154 | request.setResponseHandler(entity -> {
155 | StringBuilder sb = new StringBuilder();
156 | try {
157 | try (InputStream is = entity.getContent()) {
158 | try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) {
159 | String line;
160 | while ((line = bufferedReader.readLine()) != null) {
161 | if (status.get() == 2) {
162 | throw new TimeoutException();
163 | }
164 | status.set(1);
165 | sb.append(line).append("\n");
166 | if (line.startsWith("data:")) {
167 | dataConsumer.accept(line.substring(line.startsWith("data: ") ? 6 : 5));
168 | }
169 | }
170 | }
171 | }
172 | } catch (Exception e) {
173 | throw new RuntimeException("eventStream 请求异常", e);
174 | }
175 | return sb.toString();
176 | });
177 | return request(request);
178 | });
179 | if (futureConsumer != null) {
180 | futureConsumer.accept(submit);
181 | }
182 | try {
183 | HttpResponse httpResponse = submit.get(firstReadTimeout, TimeUnit.MILLISECONDS);
184 | if (httpResponse != null) {
185 | return httpResponse;
186 | }
187 | } catch (TimeoutException e) {
188 | if (status.get() == 0) {
189 | status.set(2);
190 | submit.cancel(true);
191 | throw e;
192 | }
193 | }
194 | return submit.get();
195 | }
196 |
197 | public static HttpResponse requestWithEventStream(HttpRequest request, Consumer dataConsumer) {
198 | if (request.getMaxSocketTimeout() == null) {
199 | request.setMaxSocketTimeout(30_000);
200 | }
201 | request.setResponseHandler(entity -> {
202 | StringBuilder sb = new StringBuilder();
203 | try {
204 | try (InputStream is = entity.getContent()) {
205 | try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) {
206 | String line;
207 | while ((line = bufferedReader.readLine()) != null) {
208 | sb.append(line).append("\n");
209 | if (line.startsWith("data:")) {
210 | dataConsumer.accept(line.substring(line.startsWith("data: ") ? 6 : 5));
211 | }
212 | }
213 | }
214 | }
215 | } catch (Exception e) {
216 | throw new RuntimeException("eventStream 请求异常", e);
217 | }
218 | return sb.toString();
219 | });
220 | return request(request);
221 | }
222 |
223 | public static int getUrlHttpStatus(String _url) {
224 | HttpURLConnection urlConnection = null;
225 | try {
226 | URL url = new URL(_url);
227 | urlConnection = (HttpURLConnection) url.openConnection();
228 | urlConnection.connect();
229 | return urlConnection.getResponseCode();
230 | } catch (Exception ignored) {
231 | return -1;
232 | } finally {
233 | if (urlConnection != null) {
234 | urlConnection.disconnect();
235 | }
236 | }
237 | }
238 |
239 | public static String getUrlLinks(Map params) {
240 | if (params == null || params.isEmpty()) {
241 | return null;
242 | }
243 | StringBuilder sb = new StringBuilder();
244 | try {
245 | String[] sortedKeys = params.keySet().toArray(new String[0]);
246 | Arrays.sort(sortedKeys);
247 | for (String key : sortedKeys) {
248 | if (key == null || key.isEmpty()) {
249 | continue;
250 | }
251 | Object value = params.get(key);
252 | sb.append(key).append("=");
253 | if (value != null) {
254 | sb.append(URLEncoder.encode(value.toString(), "UTF-8"));
255 | }
256 | sb.append("&");
257 | }
258 | } catch (UnsupportedEncodingException e) {
259 | throw new RuntimeException(e);
260 | }
261 | if (sb.length() > 0) {
262 | sb.setLength(sb.length() - 1);
263 | }
264 | return sb.toString();
265 | }
266 |
267 | @SuppressWarnings("unchecked")
268 | public static Map parseUrlLinks(String params) {
269 | Map result = new LinkedHashMap<>();
270 | if (params == null || params.isEmpty()) {
271 | return result;
272 | }
273 | for (String param : params.split("&")) {
274 | String[] split = param.split("=");
275 | String key = split[0];
276 | String value = "";
277 | if (split.length > 1) {
278 | value = split[1];
279 | }
280 | if (result.containsKey(key)) {
281 | Object o = result.get(key);
282 | if (o instanceof List) {
283 | ((List