Skip to content

Commit ca274fe

Browse files
authored
perf: init s3 (#5795)
* fix: variables refresh * fix: workflow start check * perf: init s3
1 parent 5054ccd commit ca274fe

File tree

4 files changed

+66
-17
lines changed

4 files changed

+66
-17
lines changed

document/content/docs/upgrading/4-13/4132.mdx

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,40 @@ title: 'V4.13.2(进行中)'
33
description: 'FastGPT V4.13.2 更新说明'
44
---
55

6-
# 更新指南
6+
## 更新指南
77

8-
## 增加 FastGPT/FastGPT-pro 环境变量
8+
### 1. 更新镜像:
9+
10+
- 更新 FastGPT 镜像tag: v4.13.2
11+
- 更新 FastGPT 商业版镜像tag: v4.13.2
12+
- 更新 fastgpt-plugin 镜像 tag: v0.2.4
13+
- mcp_server 无需更新
14+
- Sandbox 无需更新
15+
- AIProxy 无需更新
16+
17+
### 2. 增加 FastGPT/FastGPT-pro 环境变量
918

1019
```
11-
S3_PUBLIC_BUCKET=S3公开桶名称(公开读私有写)
20+
S3_PUBLIC_BUCKET=fastgpt_public #(公开读公开桶名称,对应原来 plugin 项目的S3_TOOL_BUCKET)
21+
S3_PRIVATE_BUCKET=fastgpt_private #(私有读私有写桶名称,对应原来 plugin 项目的S3_PLUGIN_BUCKET)
22+
```
23+
24+
### 3. 修复 fastgpt-plugin 环境变量
25+
26+
- S3_TOOL_BUCKET 改名成 S3_PUBLIC_BUCKET
27+
- S3_PLUGIN_BUCKET 改名成 S3_PRIVATE_BUCKET
28+
29+
### 4. 执行升级脚本
30+
31+
从任意终端,发起 1 个 HTTP 请求。其中 `{{rootkey}}` 替换成环境变量里的 `rootkey``{{host}}` 替换成**FastGPT 域名**
32+
33+
```bash
34+
curl --location --request POST 'https://{{host}}/api/admin/initv4132' \
35+
--header 'rootkey: {{rootkey}}' \
36+
--header 'Content-Type: application/json'
1237
```
1338

39+
会删除原先 S3 的 circleLife 策略。如果使用的是外部 S3,可能会因为不支持 circleLife 操作导
1440
## 🚀 新增内容
1541

1642
1. HTTP 工具集支持手动创建模式。

document/data/doc-last-modified.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@
113113
"document/content/docs/upgrading/4-12/4124.mdx": "2025-09-17T22:29:56+08:00",
114114
"document/content/docs/upgrading/4-13/4130.mdx": "2025-09-30T16:00:10+08:00",
115115
"document/content/docs/upgrading/4-13/4131.mdx": "2025-09-30T15:47:06+08:00",
116-
"document/content/docs/upgrading/4-13/4132.mdx": "2025-10-17T21:40:12+08:00",
116+
"document/content/docs/upgrading/4-13/4132.mdx": "2025-10-20T19:08:21+08:00",
117117
"document/content/docs/upgrading/4-8/40.mdx": "2025-08-02T19:38:37+08:00",
118118
"document/content/docs/upgrading/4-8/41.mdx": "2025-08-02T19:38:37+08:00",
119119
"document/content/docs/upgrading/4-8/42.mdx": "2025-08-02T19:38:37+08:00",

packages/service/common/s3/buckets/base.ts

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
import { Client, type RemoveOptions, type CopyConditions, type LifecycleConfig } from 'minio';
1+
import { Client, type RemoveOptions, type CopyConditions } from 'minio';
22
import {
3-
type ExtensionType,
43
type CreatePostPresignedUrlOptions,
54
type CreatePostPresignedUrlParams,
65
type CreatePostPresignedUrlResult,
@@ -9,9 +8,9 @@ import {
98
import { defaultS3Options, Mimes } from '../constants';
109
import path from 'node:path';
1110
import { MongoS3TTL } from '../schema';
12-
import { UserError } from '@fastgpt/global/common/error/utils';
1311
import { getNanoid } from '@fastgpt/global/common/string/tools';
1412
import { addHours } from 'date-fns';
13+
import { addLog } from '../../system/log';
1514

1615
export class S3BaseBucket {
1716
private _client: Client;
@@ -56,15 +55,18 @@ export class S3BaseBucket {
5655
await this.client.makeBucket(this.bucketName);
5756
}
5857
await this.options.afterInit?.();
58+
console.log(`S3 init success: ${this.name}`);
5959
};
6060
init();
6161
}
6262

6363
get name(): string {
6464
return this.bucketName;
6565
}
66-
67-
protected get client(): Client {
66+
get client(): Client {
67+
return this._client;
68+
}
69+
get externalClient(): Client {
6870
return this._externalClient ?? this._client;
6971
}
7072

@@ -93,30 +95,31 @@ export class S3BaseBucket {
9395
try {
9496
const { expiredHours } = options;
9597
const filename = params.filename;
96-
const ext = path.extname(filename).toLowerCase() as ExtensionType;
97-
const contentType = Mimes[ext] ?? 'application/octet-stream';
98-
const maxFileSize = this.options.maxFileSize as number;
98+
const ext = path.extname(filename).toLowerCase();
99+
const contentType = Mimes[ext as keyof typeof Mimes] ?? 'application/octet-stream';
100+
const maxFileSize = this.options.maxFileSize;
99101

100102
const key = (() => {
101103
if ('rawKey' in params) return params.rawKey;
102104

103105
return `${params.source}/${params.teamId}/${getNanoid(6)}-${filename}`;
104106
})();
105107

106-
const policy = this.client.newPostPolicy();
108+
const policy = this.externalClient.newPostPolicy();
107109
policy.setKey(key);
108110
policy.setBucket(this.name);
109111
policy.setContentType(contentType);
110-
policy.setContentLengthRange(1, maxFileSize);
112+
if (maxFileSize) {
113+
policy.setContentLengthRange(1, maxFileSize);
114+
}
111115
policy.setExpires(new Date(Date.now() + 10 * 60 * 1000));
112116
policy.setUserMetaData({
113-
'content-type': contentType,
114117
'content-disposition': `attachment; filename="${encodeURIComponent(filename)}"`,
115118
'origin-filename': encodeURIComponent(filename),
116119
'upload-time': new Date().toISOString()
117120
});
118121

119-
const { formData, postURL } = await this.client.presignedPostPolicy(policy);
122+
const { formData, postURL } = await this.externalClient.presignedPostPolicy(policy);
120123

121124
if (expiredHours) {
122125
await MongoS3TTL.create({
@@ -131,7 +134,8 @@ export class S3BaseBucket {
131134
fields: formData
132135
};
133136
} catch (error) {
134-
return Promise.reject(error);
137+
addLog.error('Failed to create post presigned url', error);
138+
return Promise.reject('Failed to create post presigned url');
135139
}
136140
}
137141
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { NextAPI } from '@/service/middleware/entry';
2+
import { authCert } from '@fastgpt/service/support/permission/auth/common';
3+
import { type NextApiRequest, type NextApiResponse } from 'next';
4+
import { S3Buckets } from '@fastgpt/service/common/s3/constants';
5+
6+
// 将 S3 原先的 circleLife 策略全部去掉
7+
async function handler(req: NextApiRequest, _res: NextApiResponse) {
8+
await authCert({ req, authRoot: true });
9+
10+
if (!global.s3BucketMap[S3Buckets.public]) {
11+
return Promise.reject('S3 not initialized');
12+
}
13+
14+
await global.s3BucketMap[S3Buckets.public].client.removeBucketLifecycle(S3Buckets.public);
15+
await global.s3BucketMap[S3Buckets.private].client.removeBucketLifecycle(S3Buckets.private);
16+
return {};
17+
}
18+
19+
export default NextAPI(handler);

0 commit comments

Comments
 (0)