ai-engineering-init 1.7.0 → 1.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/agents/bug-analyzer.md +103 -0
- package/.claude/agents/code-reviewer.md +115 -5
- package/.claude/agents/image-reader.md +154 -0
- package/.claude/agents/loki-runner.md +80 -0
- package/.claude/agents/mysql-runner.md +81 -0
- package/.claude/agents/requirements-analyzer.md +162 -0
- package/.claude/agents/task-fetcher.md +75 -0
- package/.claude/commands/dev.md +29 -0
- package/.claude/commands/next.md +31 -1
- package/.claude/commands/progress.md +23 -1
- package/.claude/hooks/skill-forced-eval.js +46 -62
- package/.claude/settings.json +10 -1
- package/.claude/skills/api-development/SKILL.md +179 -130
- package/.claude/skills/architecture-design/SKILL.md +102 -212
- package/.claude/skills/backend-annotations/SKILL.md +166 -220
- package/.claude/skills/bug-detective/SKILL.md +225 -186
- package/.claude/skills/code-patterns/SKILL.md +127 -244
- package/.claude/skills/collaborating-with-codex/SKILL.md +96 -113
- package/.claude/skills/crud-development/SKILL.md +226 -307
- package/.claude/skills/data-permission/SKILL.md +131 -202
- package/.claude/skills/database-ops/SKILL.md +158 -355
- package/.claude/skills/error-handler/SKILL.md +224 -285
- package/.claude/skills/file-oss-management/SKILL.md +174 -169
- package/.claude/skills/git-workflow/SKILL.md +123 -341
- package/.claude/skills/json-serialization/SKILL.md +121 -137
- package/.claude/skills/performance-doctor/SKILL.md +83 -89
- package/.claude/skills/redis-cache/SKILL.md +134 -185
- package/.claude/skills/scheduled-jobs/SKILL.md +187 -224
- package/.claude/skills/security-guard/SKILL.md +168 -276
- package/.claude/skills/sms-mail/SKILL.md +266 -228
- package/.claude/skills/social-login/SKILL.md +257 -195
- package/.claude/skills/tenant-management/SKILL.md +172 -188
- package/.claude/skills/utils-toolkit/SKILL.md +214 -222
- package/.claude/skills/websocket-sse/SKILL.md +251 -172
- package/.claude/skills/workflow-engine/SKILL.md +178 -250
- package/.codex/skills/api-development/SKILL.md +179 -130
- package/.codex/skills/architecture-design/SKILL.md +102 -212
- package/.codex/skills/backend-annotations/SKILL.md +166 -220
- package/.codex/skills/bug-detective/SKILL.md +225 -186
- package/.codex/skills/code-patterns/SKILL.md +127 -244
- package/.codex/skills/collaborating-with-codex/SKILL.md +96 -113
- package/.codex/skills/crud-development/SKILL.md +226 -307
- package/.codex/skills/data-permission/SKILL.md +131 -202
- package/.codex/skills/database-ops/SKILL.md +158 -355
- package/.codex/skills/dev/SKILL.md +476 -131
- package/.codex/skills/error-handler/SKILL.md +224 -285
- package/.codex/skills/file-oss-management/SKILL.md +174 -169
- package/.codex/skills/git-workflow/SKILL.md +123 -341
- package/.codex/skills/json-serialization/SKILL.md +121 -137
- package/.codex/skills/next/SKILL.md +186 -42
- package/.codex/skills/performance-doctor/SKILL.md +83 -89
- package/.codex/skills/progress/SKILL.md +147 -76
- package/.codex/skills/redis-cache/SKILL.md +134 -185
- package/.codex/skills/scheduled-jobs/SKILL.md +187 -224
- package/.codex/skills/security-guard/SKILL.md +168 -276
- package/.codex/skills/sms-mail/SKILL.md +266 -228
- package/.codex/skills/social-login/SKILL.md +257 -195
- package/.codex/skills/tenant-management/SKILL.md +172 -188
- package/.codex/skills/utils-toolkit/SKILL.md +214 -222
- package/.codex/skills/websocket-sse/SKILL.md +251 -172
- package/.codex/skills/workflow-engine/SKILL.md +178 -250
- package/.cursor/agents/bug-analyzer.md +102 -0
- package/.cursor/agents/code-reviewer.md +80 -97
- package/.cursor/agents/image-reader.md +154 -0
- package/.cursor/agents/loki-runner.md +80 -0
- package/.cursor/agents/mysql-runner.md +81 -0
- package/.cursor/agents/project-manager.md +1 -1
- package/.cursor/agents/requirements-analyzer.md +141 -0
- package/.cursor/agents/task-fetcher.md +75 -0
- package/.cursor/hooks/cursor-skill-eval.js +66 -6
- package/.cursor/skills/api-development/SKILL.md +179 -130
- package/.cursor/skills/architecture-design/SKILL.md +102 -212
- package/.cursor/skills/backend-annotations/SKILL.md +166 -220
- package/.cursor/skills/bug-detective/SKILL.md +225 -186
- package/.cursor/skills/code-patterns/SKILL.md +127 -244
- package/.cursor/skills/collaborating-with-codex/SKILL.md +96 -113
- package/.cursor/skills/crud-development/SKILL.md +226 -307
- package/.cursor/skills/data-permission/SKILL.md +131 -202
- package/.cursor/skills/database-ops/SKILL.md +158 -355
- package/.cursor/skills/error-handler/SKILL.md +224 -285
- package/.cursor/skills/file-oss-management/SKILL.md +174 -169
- package/.cursor/skills/git-workflow/SKILL.md +123 -341
- package/.cursor/skills/json-serialization/SKILL.md +121 -137
- package/.cursor/skills/performance-doctor/SKILL.md +83 -89
- package/.cursor/skills/redis-cache/SKILL.md +134 -185
- package/.cursor/skills/scheduled-jobs/SKILL.md +187 -224
- package/.cursor/skills/security-guard/SKILL.md +168 -276
- package/.cursor/skills/sms-mail/SKILL.md +266 -228
- package/.cursor/skills/social-login/SKILL.md +257 -195
- package/.cursor/skills/tenant-management/SKILL.md +172 -188
- package/.cursor/skills/utils-toolkit/SKILL.md +214 -222
- package/.cursor/skills/websocket-sse/SKILL.md +251 -172
- package/.cursor/skills/workflow-engine/SKILL.md +178 -250
- package/AGENTS.md +117 -540
- package/CLAUDE.md +105 -117
- package/README.md +37 -6
- package/bin/index.js +5 -1
- package/package.json +1 -1
- package/src/skills/api-development/SKILL.md +179 -130
- package/src/skills/architecture-design/SKILL.md +102 -212
- package/src/skills/backend-annotations/SKILL.md +166 -220
- package/src/skills/bug-detective/SKILL.md +225 -186
- package/src/skills/code-patterns/SKILL.md +127 -244
- package/src/skills/collaborating-with-codex/SKILL.md +96 -113
- package/src/skills/crud-development/SKILL.md +226 -307
- package/src/skills/data-permission/SKILL.md +131 -202
- package/src/skills/database-ops/SKILL.md +158 -355
- package/src/skills/error-handler/SKILL.md +224 -285
- package/src/skills/file-oss-management/SKILL.md +174 -169
- package/src/skills/git-workflow/SKILL.md +123 -341
- package/src/skills/json-serialization/SKILL.md +121 -137
- package/src/skills/performance-doctor/SKILL.md +83 -89
- package/src/skills/redis-cache/SKILL.md +134 -185
- package/src/skills/scheduled-jobs/SKILL.md +187 -224
- package/src/skills/security-guard/SKILL.md +168 -276
- package/src/skills/sms-mail/SKILL.md +266 -228
- package/src/skills/social-login/SKILL.md +257 -195
- package/src/skills/tenant-management/SKILL.md +172 -188
- package/src/skills/utils-toolkit/SKILL.md +214 -222
- package/src/skills/websocket-sse/SKILL.md +251 -172
- package/src/skills/workflow-engine/SKILL.md +178 -250
- package/.claude/skills/skill-creator/LICENSE.txt +0 -202
- package/.claude/skills/skill-creator/SKILL.md +0 -479
- package/.claude/skills/skill-creator/agents/analyzer.md +0 -274
- package/.claude/skills/skill-creator/agents/comparator.md +0 -202
- package/.claude/skills/skill-creator/agents/grader.md +0 -223
- package/.claude/skills/skill-creator/assets/eval_review.html +0 -146
- package/.claude/skills/skill-creator/eval-viewer/generate_review.py +0 -471
- package/.claude/skills/skill-creator/eval-viewer/viewer.html +0 -1325
- package/.claude/skills/skill-creator/references/schemas.md +0 -430
- package/.claude/skills/skill-creator/scripts/__init__.py +0 -0
- package/.claude/skills/skill-creator/scripts/aggregate_benchmark.py +0 -401
- package/.claude/skills/skill-creator/scripts/generate_report.py +0 -326
- package/.claude/skills/skill-creator/scripts/improve_description.py +0 -248
- package/.claude/skills/skill-creator/scripts/package_skill.py +0 -136
- package/.claude/skills/skill-creator/scripts/quick_validate.py +0 -103
- package/.claude/skills/skill-creator/scripts/run_eval.py +0 -310
- package/.claude/skills/skill-creator/scripts/run_loop.py +0 -332
- package/.claude/skills/skill-creator/scripts/utils.py +0 -47
|
@@ -10,246 +10,251 @@ description: |
|
|
|
10
10
|
- 文件元数据管理
|
|
11
11
|
- OSS服务商切换
|
|
12
12
|
|
|
13
|
-
触发词:文件上传、OSS、云存储、MinIO、阿里云、腾讯云、七牛、图片上传、文件下载、预签名、presigned、
|
|
13
|
+
触发词:文件上传、OSS、云存储、MinIO、阿里云、腾讯云、七牛、图片上传、文件下载、预签名、presigned、S3
|
|
14
14
|
---
|
|
15
15
|
|
|
16
16
|
# 文件与云存储指南
|
|
17
17
|
|
|
18
|
-
> 模块位置:`ruoyi-common/ruoyi-common-oss`
|
|
19
18
|
> 统一协议:基于 AWS S3 SDK v2,兼容所有 S3 协议云服务
|
|
20
19
|
|
|
21
|
-
##
|
|
20
|
+
## 架构概述
|
|
22
21
|
|
|
23
|
-
|
|
|
22
|
+
| 组件 | 说明 |
|
|
24
23
|
|----|------|
|
|
25
|
-
| `
|
|
26
|
-
| `
|
|
24
|
+
| `[你的OssClient]` | 统一操作入口(基于 AWS S3 SDK v2) |
|
|
25
|
+
| `S3Client` | AWS SDK 底层客户端 |
|
|
27
26
|
| `UploadResult` | 上传结果(url, filename, eTag) |
|
|
28
|
-
| `ISysOssService` | OSS 文件管理服务接口 |
|
|
29
27
|
|
|
30
28
|
---
|
|
31
29
|
|
|
32
|
-
##
|
|
30
|
+
## 一、S3 Client 初始化
|
|
33
31
|
|
|
34
32
|
```java
|
|
35
|
-
import
|
|
36
|
-
import
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
33
|
+
import software.amazon.awssdk.services.s3.S3Client;
|
|
34
|
+
import software.amazon.awssdk.services.s3.presigner.S3Presigner;
|
|
35
|
+
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
|
|
36
|
+
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
|
|
37
|
+
import software.amazon.awssdk.regions.Region;
|
|
38
|
+
|
|
39
|
+
// 通用 S3 客户端构建(兼容 MinIO / 阿里云 / 腾讯云等)
|
|
40
|
+
S3Client s3Client = S3Client.builder()
|
|
41
|
+
.endpointOverride(URI.create(endpoint))
|
|
42
|
+
.credentialsProvider(StaticCredentialsProvider.create(
|
|
43
|
+
AwsBasicCredentials.create(accessKey, secretKey)))
|
|
44
|
+
.region(Region.of(region))
|
|
45
|
+
.forcePathStyle(true) // MinIO 需要开启
|
|
46
|
+
.build();
|
|
44
47
|
```
|
|
45
48
|
|
|
46
|
-
> 内部使用 ConcurrentHashMap + ReentrantLock 双检锁缓存实例,支持多租户隔离。
|
|
47
|
-
|
|
48
49
|
---
|
|
49
50
|
|
|
50
51
|
## 二、文件上传
|
|
51
52
|
|
|
52
|
-
|
|
53
|
-
import org.dromara.common.oss.entity.UploadResult;
|
|
53
|
+
### 基础上传
|
|
54
54
|
|
|
55
|
-
|
|
56
|
-
|
|
55
|
+
```java
|
|
56
|
+
import software.amazon.awssdk.services.s3.model.PutObjectRequest;
|
|
57
|
+
import software.amazon.awssdk.core.sync.RequestBody;
|
|
57
58
|
|
|
58
|
-
//
|
|
59
|
-
|
|
59
|
+
// 上传文件
|
|
60
|
+
PutObjectRequest request = PutObjectRequest.builder()
|
|
61
|
+
.bucket(bucketName)
|
|
62
|
+
.key("images/photo.jpg")
|
|
63
|
+
.contentType("image/jpeg")
|
|
64
|
+
.build();
|
|
60
65
|
|
|
61
|
-
|
|
62
|
-
UploadResult result = client.uploadSuffix(file, ".jpg");
|
|
66
|
+
s3Client.putObject(request, RequestBody.fromFile(file.toPath()));
|
|
63
67
|
|
|
64
|
-
//
|
|
65
|
-
|
|
68
|
+
// 上传输入流
|
|
69
|
+
s3Client.putObject(request, RequestBody.fromInputStream(inputStream, contentLength));
|
|
66
70
|
|
|
67
|
-
//
|
|
68
|
-
|
|
71
|
+
// 上传字节数组
|
|
72
|
+
s3Client.putObject(request, RequestBody.fromBytes(data));
|
|
69
73
|
```
|
|
70
74
|
|
|
71
|
-
|
|
75
|
+
### 封装上传服务(推荐模式)
|
|
76
|
+
|
|
72
77
|
```java
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
+
@Service
|
|
79
|
+
@RequiredArgsConstructor
|
|
80
|
+
public class OssService {
|
|
81
|
+
|
|
82
|
+
private final S3Client s3Client;
|
|
83
|
+
private final OssProperties properties;
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* 上传文件,自动生成路径
|
|
87
|
+
*/
|
|
88
|
+
public UploadResult upload(MultipartFile file) {
|
|
89
|
+
String suffix = getFileSuffix(file.getOriginalFilename());
|
|
90
|
+
String key = generateObjectKey(suffix); // 如 2026/03/07/uuid.jpg
|
|
91
|
+
|
|
92
|
+
PutObjectRequest request = PutObjectRequest.builder()
|
|
93
|
+
.bucket(properties.getBucketName())
|
|
94
|
+
.key(key)
|
|
95
|
+
.contentType(file.getContentType())
|
|
96
|
+
.build();
|
|
97
|
+
|
|
98
|
+
s3Client.putObject(request,
|
|
99
|
+
RequestBody.fromInputStream(file.getInputStream(), file.getSize()));
|
|
100
|
+
|
|
101
|
+
return UploadResult.builder()
|
|
102
|
+
.url(properties.getDomain() + "/" + key)
|
|
103
|
+
.filename(key)
|
|
104
|
+
.build();
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
private String generateObjectKey(String suffix) {
|
|
108
|
+
String datePath = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy/MM/dd"));
|
|
109
|
+
return datePath + "/" + UUID.randomUUID() + suffix;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
78
112
|
```
|
|
79
113
|
|
|
80
114
|
---
|
|
81
115
|
|
|
82
|
-
##
|
|
83
|
-
|
|
84
|
-
> 只有 3 个字段,使用 Lombok `@Builder`。
|
|
85
|
-
|
|
86
|
-
| 字段 | 类型 | 说明 |
|
|
87
|
-
|------|------|------|
|
|
88
|
-
| `url` | String | 文件访问URL |
|
|
89
|
-
| `filename` | String | 文件名/对象键(**小写 n**) |
|
|
90
|
-
| `eTag` | String | 文件校验标记 |
|
|
116
|
+
## 三、文件下载
|
|
91
117
|
|
|
92
118
|
```java
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
119
|
+
import software.amazon.awssdk.services.s3.model.GetObjectRequest;
|
|
120
|
+
import software.amazon.awssdk.core.ResponseInputStream;
|
|
121
|
+
|
|
122
|
+
// 下载到输出流(推荐用于HTTP响应)
|
|
123
|
+
GetObjectRequest getRequest = GetObjectRequest.builder()
|
|
124
|
+
.bucket(bucketName)
|
|
125
|
+
.key("images/photo.jpg")
|
|
126
|
+
.build();
|
|
127
|
+
|
|
128
|
+
ResponseInputStream<?> response = s3Client.getObject(getRequest);
|
|
129
|
+
|
|
130
|
+
// 写入 HTTP 响应
|
|
131
|
+
try (InputStream is = response) {
|
|
132
|
+
httpResponse.setContentType("image/jpeg");
|
|
133
|
+
httpResponse.setContentLengthLong(response.response().contentLength());
|
|
134
|
+
is.transferTo(httpResponse.getOutputStream());
|
|
135
|
+
}
|
|
96
136
|
```
|
|
97
137
|
|
|
98
138
|
---
|
|
99
139
|
|
|
100
|
-
##
|
|
140
|
+
## 四、文件删除
|
|
101
141
|
|
|
102
142
|
```java
|
|
103
|
-
|
|
104
|
-
Path tempFile = client.fileDownload("images/photo.jpg");
|
|
143
|
+
import software.amazon.awssdk.services.s3.model.DeleteObjectRequest;
|
|
105
144
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
145
|
+
DeleteObjectRequest deleteRequest = DeleteObjectRequest.builder()
|
|
146
|
+
.bucket(bucketName)
|
|
147
|
+
.key("images/photo.jpg")
|
|
148
|
+
.build();
|
|
110
149
|
|
|
111
|
-
|
|
112
|
-
InputStream is = client.getObjectContent("images/photo.jpg");
|
|
150
|
+
s3Client.deleteObject(deleteRequest);
|
|
113
151
|
```
|
|
114
152
|
|
|
115
153
|
---
|
|
116
154
|
|
|
117
|
-
##
|
|
155
|
+
## 五、预签名 URL
|
|
118
156
|
|
|
119
157
|
```java
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
158
|
+
import software.amazon.awssdk.services.s3.presigner.S3Presigner;
|
|
159
|
+
import software.amazon.awssdk.services.s3.presigner.model.*;
|
|
160
|
+
|
|
161
|
+
S3Presigner presigner = S3Presigner.builder()
|
|
162
|
+
.endpointOverride(URI.create(endpoint))
|
|
163
|
+
.credentialsProvider(credentialsProvider)
|
|
164
|
+
.region(Region.of(region))
|
|
165
|
+
.build();
|
|
123
166
|
|
|
124
167
|
// 下载预签名URL
|
|
125
|
-
|
|
168
|
+
GetObjectPresignRequest getPresignRequest = GetObjectPresignRequest.builder()
|
|
169
|
+
.signatureDuration(Duration.ofMinutes(60))
|
|
170
|
+
.getObjectRequest(b -> b.bucket(bucketName).key("images/photo.jpg"))
|
|
171
|
+
.build();
|
|
172
|
+
String downloadUrl = presigner.presignGetObject(getPresignRequest).url().toString();
|
|
126
173
|
|
|
127
174
|
// 上传预签名URL(前端直传)
|
|
128
|
-
|
|
129
|
-
|
|
175
|
+
PutObjectPresignRequest putPresignRequest = PutObjectPresignRequest.builder()
|
|
176
|
+
.signatureDuration(Duration.ofHours(1))
|
|
177
|
+
.putObjectRequest(b -> b.bucket(bucketName).key("images/upload.jpg"))
|
|
178
|
+
.build();
|
|
179
|
+
String uploadUrl = presigner.presignPutObject(putPresignRequest).url().toString();
|
|
130
180
|
```
|
|
131
181
|
|
|
132
182
|
---
|
|
133
183
|
|
|
134
|
-
## 六、
|
|
184
|
+
## 六、Controller 接口(设计模式)
|
|
135
185
|
|
|
136
186
|
```java
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
**上传接口规范:**
|
|
160
|
-
```java
|
|
161
|
-
// 必须使用 @RequestPart("file"),必须指定 consumes
|
|
162
|
-
@PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
|
|
163
|
-
public R<SysOssUploadVo> upload(@RequestPart("file") MultipartFile file) {
|
|
164
|
-
SysOssVo oss = ossService.upload(file);
|
|
165
|
-
SysOssUploadVo uploadVo = new SysOssUploadVo();
|
|
166
|
-
uploadVo.setUrl(oss.getUrl());
|
|
167
|
-
uploadVo.setFileName(oss.getOriginalName());
|
|
168
|
-
uploadVo.setOssId(oss.getOssId().toString());
|
|
169
|
-
return R.ok(uploadVo);
|
|
187
|
+
@RestController
|
|
188
|
+
@RequiredArgsConstructor
|
|
189
|
+
@RequestMapping("/api/oss")
|
|
190
|
+
public class OssController {
|
|
191
|
+
|
|
192
|
+
private final OssService ossService;
|
|
193
|
+
|
|
194
|
+
@PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
|
|
195
|
+
public UploadResult upload(@RequestPart("file") MultipartFile file) {
|
|
196
|
+
return ossService.upload(file);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
@GetMapping("/download/{id}")
|
|
200
|
+
public void download(@PathVariable Long id, HttpServletResponse response) throws IOException {
|
|
201
|
+
ossService.download(id, response);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
@DeleteMapping("/{ids}")
|
|
205
|
+
public void delete(@PathVariable List<Long> ids) {
|
|
206
|
+
ossService.deleteByIds(ids);
|
|
207
|
+
}
|
|
170
208
|
}
|
|
171
209
|
```
|
|
172
210
|
|
|
173
|
-
**SysOssUploadVo**:`url`(String) / `fileName`(String) / `ossId`(String)
|
|
174
|
-
|
|
175
211
|
---
|
|
176
212
|
|
|
177
|
-
##
|
|
213
|
+
## 七、配置模型
|
|
214
|
+
|
|
215
|
+
```yaml
|
|
216
|
+
# application.yml
|
|
217
|
+
oss:
|
|
218
|
+
endpoint: https://s3.amazonaws.com # 或 MinIO/阿里云/腾讯云端点
|
|
219
|
+
access-key: your-access-key
|
|
220
|
+
secret-key: your-secret-key
|
|
221
|
+
bucket-name: your-bucket
|
|
222
|
+
region: us-east-1
|
|
223
|
+
domain: https://cdn.example.com # 自定义域名(可选)
|
|
224
|
+
```
|
|
178
225
|
|
|
179
226
|
```java
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
227
|
+
@Data
|
|
228
|
+
@ConfigurationProperties(prefix = "oss")
|
|
229
|
+
public class OssProperties {
|
|
230
|
+
private String endpoint;
|
|
231
|
+
private String accessKey;
|
|
232
|
+
private String secretKey;
|
|
233
|
+
private String bucketName;
|
|
234
|
+
private String region;
|
|
235
|
+
private String domain;
|
|
236
|
+
}
|
|
188
237
|
```
|
|
189
238
|
|
|
190
|
-
> 推荐通过 `ISysOssService.upload()` 上传,会自动保存数据库记录。
|
|
191
|
-
> 直接使用 `OssClient` 上传不会有数据库记录。
|
|
192
|
-
|
|
193
|
-
> 完整 Service 实现代码详见 [references/service-impl.md](references/service-impl.md)
|
|
194
|
-
|
|
195
|
-
---
|
|
196
|
-
|
|
197
|
-
## 九、数据库实体
|
|
198
|
-
|
|
199
|
-
> 完整实体/VO/BO 定义详见 [references/entities.md](references/entities.md)
|
|
200
|
-
|
|
201
|
-
**SysOss 关键字段:**
|
|
202
|
-
|
|
203
|
-
| 字段 | 说明 |
|
|
204
|
-
|------|------|
|
|
205
|
-
| `ossId` | 主键 |
|
|
206
|
-
| `fileName` | OSS对象键 |
|
|
207
|
-
| `originalName` | 原始文件名 |
|
|
208
|
-
| `fileSuffix` | 后缀名 |
|
|
209
|
-
| `url` | 访问URL |
|
|
210
|
-
| `ext1` | 扩展字段(JSON,存储 SysOssExt) |
|
|
211
|
-
| `service` | 服务商标识 |
|
|
212
|
-
|
|
213
|
-
---
|
|
214
|
-
|
|
215
|
-
## 十、配置(sys_oss_config 表)
|
|
216
|
-
|
|
217
|
-
| 字段 | 说明 |
|
|
218
|
-
|------|------|
|
|
219
|
-
| `config_key` | 配置标识(aliyun、minio等) |
|
|
220
|
-
| `access_key` / `secret_key` | 认证信息 |
|
|
221
|
-
| `bucket_name` | 存储桶 |
|
|
222
|
-
| `prefix` | 路径前缀 |
|
|
223
|
-
| `endpoint` | 服务端点 |
|
|
224
|
-
| `domain` | 自定义域名 |
|
|
225
|
-
| `is_https` | 是否HTTPS(Y/N) |
|
|
226
|
-
| `region` | 区域 |
|
|
227
|
-
| `access_policy` | 0-private, 1-public, 2-custom |
|
|
228
|
-
|
|
229
|
-
> 配置从 Redis 读取(`CacheNames.SYS_OSS_CONFIG`),私有桶文件自动生成 120 秒预签名URL。
|
|
230
|
-
|
|
231
239
|
---
|
|
232
240
|
|
|
233
|
-
##
|
|
241
|
+
## 八、服务商对照
|
|
234
242
|
|
|
235
|
-
|
|
|
236
|
-
|
|
237
|
-
| `
|
|
238
|
-
|
|
|
239
|
-
| `
|
|
240
|
-
| `
|
|
241
|
-
|
|
|
242
|
-
| `throw ServiceException.of("msg")` | `throw new ServiceException("msg")` |
|
|
243
|
-
| `client.copyFile/listFiles/getFileMetadata` | 不存在 |
|
|
243
|
+
| 服务商 | endpoint 示例 | 备注 |
|
|
244
|
+
|--------|-------------|------|
|
|
245
|
+
| 阿里云 OSS | `https://oss-cn-hangzhou.aliyuncs.com` | S3 兼容 |
|
|
246
|
+
| 腾讯云 COS | `https://cos.ap-guangzhou.myqcloud.com` | S3 兼容 |
|
|
247
|
+
| 七牛云 | `https://s3-cn-south-1.qiniucs.com` | S3 兼容 |
|
|
248
|
+
| MinIO | `http://localhost:9000` | 需 `forcePathStyle(true)` |
|
|
249
|
+
| AWS S3 | `https://s3.amazonaws.com` | 原生支持 |
|
|
244
250
|
|
|
245
251
|
---
|
|
246
252
|
|
|
247
|
-
##
|
|
253
|
+
## 九、设计要点
|
|
248
254
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
| SysOssServiceImpl | `ruoyi-modules/ruoyi-system/.../service/impl/SysOssServiceImpl.java` |
|
|
255
|
+
1. **统一封装**:通过 S3 协议统一对接多个云服务商,切换只需改配置
|
|
256
|
+
2. **路径生成**:按日期+UUID生成对象路径,避免冲突
|
|
257
|
+
3. **私有桶**:私有桶文件通过预签名URL访问,设置合理的过期时间
|
|
258
|
+
4. **文件记录**:上传后保存数据库记录,关联业务数据
|
|
259
|
+
5. **大文件**:超过 100MB 考虑分片上传(`CreateMultipartUpload`)
|
|
260
|
+
6. **安全**:前端直传使用预签名URL,不暴露密钥
|