Browse Source

feat: 更新文档

master
yuanjs@qutke.com 2 weeks ago
parent
commit
2d1c7934f5
  1. 292
      README.md
  2. 12
      src/main/java/org/ycloud/aipan/config/AmazonS3Config.java
  3. 6
      src/main/java/org/ycloud/aipan/enums/BizCodeEnum.java
  4. 36
      src/main/java/org/ycloud/aipan/service/impl/AccountFileServiceImpl.java
  5. 16
      src/main/resources/application.yml
  6. 4
      src/test/java/org/ycloud/aipan/AmazonS3ClientTests.java

292
README.md

@ -4031,21 +4031,7 @@ public JsonData list(@RequestParam(value = "parent_id")Long parentId){
#### AWS-S3大文件上传API测试合并分片实战
#### 第6集 AWS-S3大文件上传API测试合并分片实战
**简介: AWS-S3大文件上传API测试合并分片实战**
* 需求:测试下面相关API * 需求:测试下面相关API
@ -4059,7 +4045,7 @@ public JsonData list(@RequestParam(value = "parent_id")Long parentId){
* 测试实战 * 测试实战
``` ```java
// 测试合并分片的方法 // 测试合并分片的方法
@Test @Test
public void testMergeChunks() { public void testMergeChunks() {
@ -4101,15 +4087,7 @@ public JsonData list(@RequestParam(value = "parent_id")Long parentId){
#### AWS-S3大文件上传API测试上传进度实战
#### 第7集 AWS-S3大文件上传API测试上传进度实战
**简介: AWS-S3大文件上传API测试上传进度实战**
* 需求:测试下面相关API * 需求:测试下面相关API
@ -4123,7 +4101,7 @@ public JsonData list(@RequestParam(value = "parent_id")Long parentId){
* 测试实战 * 测试实战
``` ```java
@Test @Test
// 测试列出分片上传的各个分片信息 // 测试列出分片上传的各个分片信息
public void testListParts() { public void testListParts() {
@ -4160,18 +4138,7 @@ public JsonData list(@RequestParam(value = "parent_id")Long parentId){
``` ```
#### 存储引擎StoreEngine大文件上传API封装
#### 第8集 存储引擎StoreEngine大文件上传API封装
**简介: 存储引擎StoreEngine大文件上传API封装**
* 需求 * 需求
@ -4181,7 +4148,7 @@ public JsonData list(@RequestParam(value = "parent_id")Long parentId){
* 接口 * 接口
``` ```java
/** /**
* 查询分片数据 * 查询分片数据
* @param bucketName 存储桶名称 * @param bucketName 存储桶名称
@ -4225,7 +4192,7 @@ public JsonData list(@RequestParam(value = "parent_id")Long parentId){
* 实现 * 实现
``` ```java
@Override @Override
public PartListing listMultipart(String bucketName, String objectKey, String uploadId) { public PartListing listMultipart(String bucketName, String objectKey, String uploadId) {
try { try {
@ -4278,27 +4245,11 @@ public JsonData list(@RequestParam(value = "parent_id")Long parentId){
``` ```
### 大文件上传接口开发和全链路测试
#### 初始化分片上传任务接口设计和开发实战
![logo](D:/学习/2025/AI智能化云盘学习笔记/笔记/img/image-20230918114907133-5008948.png) **愿景:"IT路上的持续充电平台,让技术不再难学"**
**更多高级课程请访问 xdclass.net**
### 第十四章 大文件上传接口开发和全链路测试
#### 第1集 初始化分片上传任务接口设计和开发实战
**简介: 初始化分片上传任务接口设计和开发实战**
* 需求 * 需求
@ -4307,7 +4258,7 @@ public JsonData list(@RequestParam(value = "parent_id")Long parentId){
* 数据库文件分片信息表说明 * 数据库文件分片信息表说明
``` ```java
CREATE TABLE `file_chunk` ( CREATE TABLE `file_chunk` (
`id` bigint NOT NULL, `id` bigint NOT NULL,
`identifier` varchar(500) NOT NULL COMMENT '文件唯一标识(md5)', `identifier` varchar(500) NOT NULL COMMENT '文件唯一标识(md5)',
@ -4336,7 +4287,7 @@ public JsonData list(@RequestParam(value = "parent_id")Long parentId){
* 编码实战 * 编码实战
``` ```java
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public FileChunkDTO initFileChunkTask(FileChunkInitTaskReq req) { public FileChunkDTO initFileChunkTask(FileChunkInitTaskReq req) {
@ -4376,25 +4327,7 @@ public JsonData list(@RequestParam(value = "parent_id")Long parentId){
#### 临时分片上传地址接口设计和开发实战
#### 第2集 临时分片上传地址接口设计和开发实战
**简介: 临时分片上传地址接口设计和开发实战**
* 需求 * 需求
@ -4408,7 +4341,7 @@ public JsonData list(@RequestParam(value = "parent_id")Long parentId){
* 编码实战 * 编码实战
``` ```java
@Override @Override
public String genPreSignUploadUrl(Long accountId, String identifier, Integer partNumber) { public String genPreSignUploadUrl(Long accountId, String identifier, Integer partNumber) {
FileChunkDO task = fileChunkMapper.selectOne(new QueryWrapper<FileChunkDO>().lambda().eq(FileChunkDO::getIdentifier, identifier).eq(FileChunkDO::getAccountId, accountId)); FileChunkDO task = fileChunkMapper.selectOne(new QueryWrapper<FileChunkDO>().lambda().eq(FileChunkDO::getIdentifier, identifier).eq(FileChunkDO::getAccountId, accountId));
@ -4429,25 +4362,7 @@ public JsonData list(@RequestParam(value = "parent_id")Long parentId){
#### 合并分片文件接口设计和开发实战
#### 第3集 合并分片文件接口设计和开发实战
**简介: 合并分片文件接口设计和开发实战**
* 需求 * 需求
@ -4464,7 +4379,7 @@ public JsonData list(@RequestParam(value = "parent_id")Long parentId){
* 编码实战 * 编码实战
``` ```java
public void mergeFileChunk(FileChunkMergeReq req) { public void mergeFileChunk(FileChunkMergeReq req) {
//获取任务和分片列表,检查是否足够合并 //获取任务和分片列表,检查是否足够合并
@ -4522,21 +4437,7 @@ public JsonData list(@RequestParam(value = "parent_id")Long parentId){
#### 查询分片上传进度接口设计和开发实战
#### 第4集 查询分片上传进度接口设计和开发实战
**简介: 查询分片上传进度接口设计和开发实战**
* 需求 * 需求
@ -4550,7 +4451,7 @@ public JsonData list(@RequestParam(value = "parent_id")Long parentId){
* 编码实战 * 编码实战
``` ```java
@Override @Override
public FileChunkDTO listFileChunk(Long accountId, String identifier) { public FileChunkDTO listFileChunk(Long accountId, String identifier) {
@ -4579,27 +4480,7 @@ public JsonData list(@RequestParam(value = "parent_id")Long parentId){
#### 大文件分片上传全链路测试方案设计
#### 第5集 大文件分片上传全链路测试方案设计
**简介: 大文件分片上传全链路测试方案设计**
* 需求 * 需求
@ -4607,8 +4488,6 @@ public JsonData list(@RequestParam(value = "parent_id")Long parentId){
* 缺少前端的情况下,大文件如何分片进行测试? * 缺少前端的情况下,大文件如何分片进行测试?
* 如何测试大文件上传相关接口? * 如何测试大文件上传相关接口?
<img src="D:/学习/2025/AI智能化云盘学习笔记/笔记/img/image-20250124102709550.png" alt="image-20250124102709550" style="zoom:30%;" />
* 测试思路 * 测试思路
* 使用后端Java代码进行文件读取 * 使用后端Java代码进行文件读取
@ -4626,7 +4505,7 @@ public JsonData list(@RequestParam(value = "parent_id")Long parentId){
* 使用后端Java代码进行文件读取 * 使用后端Java代码进行文件读取
* 根据进行切割成不同的小文件 * 根据进行切割成不同的小文件
``` ```java
SpringBootTest SpringBootTest
@Slf4j @Slf4j
class FileChunkUploadTests { class FileChunkUploadTests {
@ -4690,25 +4569,7 @@ public JsonData list(@RequestParam(value = "parent_id")Long parentId){
#### 大文件分片上传全链路测试代码实战《上》
#### 第6集 大文件分片上传全链路测试代码实战《上》
**简介: 大文件分片上传后端全链路测试方案实战**
* 需求 * 需求
@ -4720,7 +4581,7 @@ public JsonData list(@RequestParam(value = "parent_id")Long parentId){
* 编码实战 * 编码实战
``` ```java
/** /**
* 第1步,创建分片上传任务 * 第1步,创建分片上传任务
*/ */
@ -4794,29 +4655,11 @@ public JsonData list(@RequestParam(value = "parent_id")Long parentId){
#### 大文件分片上传全链路测试代码实战《下》
#### 第7集 大文件分片上传全链路测试代码实战《下》
**简介: 大文件分片上传后端全链路测试方案实战**
* 需求 * 需求
* 测试大文件上传全链路代码 * 测试大文件上传全链路代码
<img src="D:/学习/2025/AI智能化云盘学习笔记/笔记/img/image-20250124153127049.png" alt="image-20250124153127049" style="zoom:60%;" />
* 测试实战 * 测试实战
* 检查分片文件是否生成 * 检查分片文件是否生成
* 检查MinIO是否有对应的文件 * 检查MinIO是否有对应的文件
@ -4827,26 +4670,11 @@ public JsonData list(@RequestParam(value = "parent_id")Long parentId){
### 网盘文件分享模块设计和开发实战
#### 文件分享转存需求背景和数据库表说明
![logo](D:/学习/2025/AI智能化云盘学习笔记/笔记/img/image-20230918114907133-5008948.png) **愿景:"IT路上的持续充电平台,让技术不再难学"**
**更多高级课程请访问 xdclass.net**
### 第十五章 网盘文件分享模块设计和开发实战
#### 第1集 文件分享转存需求背景和数据库表说明
**简介: 文件分享转存需求背景和数据库表说明**
* 需求 * 需求
* 老王有几十G《冰冰的游泳视频》存储在小滴网盘上面 * 老王有几十G《冰冰的游泳视频》存储在小滴网盘上面
@ -4872,17 +4700,7 @@ public JsonData list(@RequestParam(value = "parent_id")Long parentId){
#### 文件分享枚举定义和分享列表接口开发
#### 第2集 文件分享枚举定义和分享列表接口开发
**简介: 文件分享枚举定义和分享列表接口开发**
* 需求 * 需求
@ -4893,7 +4711,7 @@ public JsonData list(@RequestParam(value = "parent_id")Long parentId){
* 提取码枚举 * 提取码枚举
``` ```java
@Getter @Getter
public enum ShareTypeEnum { public enum ShareTypeEnum {
@ -4911,7 +4729,7 @@ public JsonData list(@RequestParam(value = "parent_id")Long parentId){
* 分享状态 * 分享状态
``` ```java
/** /**
* 分享状态 used正常, expired已失效, cancled取消 * 分享状态 used正常, expired已失效, cancled取消
*/ */
@ -4924,7 +4742,7 @@ public JsonData list(@RequestParam(value = "parent_id")Long parentId){
* 分享链接时效性枚举 * 分享链接时效性枚举
``` ```java
//分享类型(0 永久有效;1: 7天有效;2: 30天有效) //分享类型(0 永久有效;1: 7天有效;2: 30天有效)
@AllArgsConstructor @AllArgsConstructor
@Getter @Getter
@ -4957,7 +4775,7 @@ public JsonData list(@RequestParam(value = "parent_id")Long parentId){
* 我的分享列表接口 * 我的分享列表接口
``` ```java
@Override @Override
public List<ShareDTO> listShare() { public List<ShareDTO> listShare() {
Long accountId = LoginInterceptor.threadLocal.get().getId(); Long accountId = LoginInterceptor.threadLocal.get().getId();
@ -4970,18 +4788,7 @@ public JsonData list(@RequestParam(value = "parent_id")Long parentId){
#### AI智能化云盘-创建文件分享接口开发实战
#### 第3集 AI智能化云盘-创建文件分享接口开发实战
**简介: AI智能化云盘-创建文件分享接口开发实战**
* 需求 * 需求
@ -4998,7 +4805,7 @@ public JsonData list(@RequestParam(value = "parent_id")Long parentId){
* 编码实战 * 编码实战
``` ```java
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public ShareDTO createShare(ShareCreateReq req) { public ShareDTO createShare(ShareCreateReq req) {
@ -5055,21 +4862,7 @@ public JsonData list(@RequestParam(value = "parent_id")Long parentId){
#### 批量取消分享接口实战和文件移动Bug修复
#### 第4集 批量取消分享接口实战和文件移动Bug修复
**简介: 批量取消分享接口实战和文件移动Bug修复**
* 需求 * 需求
@ -5085,7 +4878,7 @@ public JsonData list(@RequestParam(value = "parent_id")Long parentId){
* 编码实战 * 编码实战
``` ```java
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void cancelShare(ShareCancelReq req) { public void cancelShare(ShareCancelReq req) {
//1、校验分享ID列表权限是否合格 //1、校验分享ID列表权限是否合格
@ -5108,7 +4901,7 @@ public JsonData list(@RequestParam(value = "parent_id")Long parentId){
* 文件移动Bug修复(几个细心的同学发现了Bug,多数同学没发现) * 文件移动Bug修复(几个细心的同学发现了Bug,多数同学没发现)
``` ```java
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void moveBatch(FileBatchReq req) { public void moveBatch(FileBatchReq req) {
@ -5134,17 +4927,7 @@ public JsonData list(@RequestParam(value = "parent_id")Long parentId){
#### 链路接口测试-创建-查看-取消分享接口
#### 第5集 链路接口测试-创建-查看-取消分享接口
**简介: 链路接口测试-创建-查看-取消分享接口**
* 接口测试需求 * 接口测试需求
* 测试创建文件分享链接接口 * 测试创建文件分享链接接口
@ -5153,8 +4936,6 @@ public JsonData list(@RequestParam(value = "parent_id")Long parentId){
* 测试实战 * 测试实战
<img src="D:/学习/2025/AI智能化云盘学习笔记/笔记/img/image-20250210121918635.png" alt="image-20250210121918635" style="zoom:50%;" />
@ -5184,9 +4965,6 @@ public JsonData list(@RequestParam(value = "parent_id")Long parentId){
![logo](D:/学习/2025/AI智能化云盘学习笔记/笔记/img/image-20230918114907133-5008948.png) **愿景:"IT路上的持续充电平台,让技术不再难学"**
**更多高级课程请访问 xdclass.net**
### 第十六章 自定义注解+AOP实战文件分享设计实战 ### 第十六章 自定义注解+AOP实战文件分享设计实战

12
src/main/java/org/ycloud/aipan/config/AmazonS3Config.java

@ -21,10 +21,10 @@ import org.springframework.context.annotation.Configuration;
public class AmazonS3Config { public class AmazonS3Config {
// 注入Minio配置类,用于获取访问密钥和Endpoint等信息 // 注入Minio配置类,用于获取访问密钥和Endpoint等信息
// @Resource
// private MinioConfig minioConfig;
@Resource @Resource
private AliOssConfig aliOssConfig; private MinioConfig minioConfig;
// @Resource
// private AliOssConfig aliOssConfig;
/** /**
* 创建并配置Amazon S3客户端 * 创建并配置Amazon S3客户端
@ -41,16 +41,16 @@ public class AmazonS3Config {
config.setConnectionTimeout(5000); config.setConnectionTimeout(5000);
config.setUseExpectContinue(true); config.setUseExpectContinue(true);
// 使用配置中的访问密钥和秘密密钥创建AWS凭证 // 使用配置中的访问密钥和秘密密钥创建AWS凭证
AWSCredentials credentials = new BasicAWSCredentials(aliOssConfig.getAccessKey(), aliOssConfig.getAccessSecret()); AWSCredentials credentials = new BasicAWSCredentials(minioConfig.getAccessKey(), minioConfig.getAccessSecret());
// 设置Endpoint // 设置Endpoint
AwsClientBuilder.EndpointConfiguration endpointConfiguration = new AwsClientBuilder AwsClientBuilder.EndpointConfiguration endpointConfiguration = new AwsClientBuilder
.EndpointConfiguration(aliOssConfig.getEndpoint(), Regions.US_EAST_1.name()); .EndpointConfiguration(minioConfig.getEndpoint(), Regions.US_EAST_1.name());
// 使用以上配置创建并返回Amazon S3客户端实例 // 使用以上配置创建并返回Amazon S3客户端实例
return AmazonS3ClientBuilder.standard() return AmazonS3ClientBuilder.standard()
.withClientConfiguration(config) .withClientConfiguration(config)
.withCredentials(new AWSStaticCredentialsProvider(credentials)) .withCredentials(new AWSStaticCredentialsProvider(credentials))
.withEndpointConfiguration(endpointConfiguration) .withEndpointConfiguration(endpointConfiguration)
.withPathStyleAccessEnabled(false) // mino设置为true,oss设置为false .withPathStyleAccessEnabled(true) // mino设置为true,oss设置为false
.build(); .build();

6
src/main/java/org/ycloud/aipan/enums/BizCodeEnum.java

@ -31,7 +31,11 @@ public enum BizCodeEnum {
SHARE_CANCEL(260406, "分享已取消"), SHARE_CANCEL(260406, "分享已取消"),
SHARE_EXPIRED(260407, "分享已过期"), SHARE_EXPIRED(260407, "分享已过期"),
SHARE_FILE_ILLEGAL(260408, "分享的文件不合规"), SHARE_FILE_ILLEGAL(260408, "分享的文件不合规"),
FILE_BATCH_UPDATE_ERROR(270101,"文件批量操作错误" ); FILE_BATCH_UPDATE_ERROR(270101,"文件批量操作错误" ),
FILE_DIR_NOT_EXIST(270102,"用户的上级目录不存在" ),
FILE_DIR_ERROR(270103,"用户的上级目录错误" ),
;
private final int code; private final int code;
private final String message; private final String message;

36
src/main/java/org/ycloud/aipan/service/impl/AccountFileServiceImpl.java

@ -58,7 +58,32 @@ public class AccountFileServiceImpl implements AccountFileService {
@Override @Override
public Long createFolder(FolderCreateReq req) { public Long createFolder(FolderCreateReq req) {
AccountFileDTO accountFileDTO = AccountFileDTO.builder().accountId(req.getAccountId()) // 创建文件夹时,父ID必须是该用户下的
if (req.getParentId() != null) {
if (req.getParentId() == 0L) {
// 用户根目录不能操作
throw new BizException(BizCodeEnum.FILE_DIR_NOT_EXIST);
}
// 校验该用户下是否存在该父级id
Long sum = accountFileMapper.selectCount(new QueryWrapper<AccountFileDO>()
.eq("id", req.getParentId()).eq("account_id", req.getAccountId()));
if (sum == 0) {
throw new BizException(BizCodeEnum.FILE_DIR_NOT_EXIST);
}
if (sum > 1) {
throw new BizException(BizCodeEnum.FILE_DIR_ERROR);
}
} else {
AccountFileDO fileUser = accountFileMapper.selectOne(new QueryWrapper<AccountFileDO>()
.eq("parent_id", 0L).eq("account_id", req.getAccountId()));
if (fileUser == null) {
// 用户根目录不存在
throw new BizException(BizCodeEnum.FILE_DIR_ERROR);
}
req.setParentId(fileUser.getId());
}
AccountFileDTO accountFileDTO = AccountFileDTO.builder()
.accountId(req.getAccountId())
.parentId(req.getParentId()) .parentId(req.getParentId())
.fileName(req.getFolderName()) .fileName(req.getFolderName())
.isDir(FolderFlagEnum.YES.getCode()).build(); .isDir(FolderFlagEnum.YES.getCode()).build();
@ -141,10 +166,12 @@ public class AccountFileServiceImpl implements AccountFileService {
return rootFolderList; return rootFolderList;
} }
/** /**
* 查询文件树接口 非递归方式 * 查询文件树接口 非递归方式
* 1查询用户全部文件夹 * 1查询用户全部文件夹
* 2拼装文件树 * 2拼装文件树
*
* @param accountId * @param accountId
* @return * @return
*/ */
@ -238,6 +265,7 @@ public class AccountFileServiceImpl implements AccountFileService {
* 检查目标文件夹ID是否合法,包括子文件夹 * 检查目标文件夹ID是否合法,包括子文件夹
* 1目标的文件ID不能是文件 * 1目标的文件ID不能是文件
* 2要操作的文件列表不能包括目标文件ID * 2要操作的文件列表不能包括目标文件ID
*
* @param req * @param req
*/ */
private void checkTargetParentIdLegal(FileBatchReq req) { private void checkTargetParentIdLegal(FileBatchReq req) {
@ -251,8 +279,10 @@ public class AccountFileServiceImpl implements AccountFileService {
throw new BizException(BizCodeEnum.FILE_TARGET_PARENT_ILLEGAL); throw new BizException(BizCodeEnum.FILE_TARGET_PARENT_ILLEGAL);
} }
} }
/** /**
* 检查被移动的文件ID是否合法 * 检查被移动的文件ID是否合法
*
* @param fileIds * @param fileIds
* @param accountId * @param accountId
* @return * @return
@ -273,6 +303,7 @@ public class AccountFileServiceImpl implements AccountFileService {
/** /**
* 保存文件和账号文件的关系到数据库 * 保存文件和账号文件的关系到数据库
*
* @param req * @param req
* @param storeFileObjectKey * @param storeFileObjectKey
*/ */
@ -309,15 +340,16 @@ public class AccountFileServiceImpl implements AccountFileService {
/** /**
* 上传文件到存储引擎返回存储的文件路径 * 上传文件到存储引擎返回存储的文件路径
*
* @param req * @param req
* @return * @return
*/ */
private String storeFile(FileUploadReq req) { private String storeFile(FileUploadReq req) {
String objectKey = CommonUtil.getFilePath(req.getFilename()); String objectKey = CommonUtil.getFilePath(req.getFilename());
fileStoreEngine.upload(minioConfig.getBucketName(), objectKey, req.getFile()); fileStoreEngine.upload(minioConfig.getBucketName(), objectKey, req.getFile());
return objectKey; return objectKey;
} }
/** /**
* 处理用户和文件的关系存储文件和文件夹都是可以的 * 处理用户和文件的关系存储文件和文件夹都是可以的
* <p> * <p>

16
src/main/resources/application.yml

@ -4,12 +4,16 @@ server:
spring: spring:
application: application:
name: ycloud-aipan name: ycloud-aipan
servlet:
multipart:
max-file-size: 10MB
max-request-size: 10MB
datasource: datasource:
driver-class-name: com.mysql.cj.jdbc.Driver driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://47.98.137.138:3306/ycloud-aipan?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true url: jdbc:mysql://117.72.43.105:3306/ycloud-aipan?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
username: root username: root
password: Yuan625621105 password: Yuan625621105.
data: data:
redis: redis:
@ -40,10 +44,12 @@ mybatis-plus:
# minio配置 # minio配置
minio: minio:
endpoint: http://192.168.60.124:9000 endpoint: http://106.75.254.18:9000
access-key: minio_root access-key: yuanjs
access-secret: minio_123456 access-secret: yuanjs625621105
# bucket需要创建,程序启动后不会自动创建
bucket-name: ai-pan bucket-name: ai-pan
# 头像要使返回的url直接可访问,需要再创建bucket后设置访问策略为public
avatar-bucket-name: avatar avatar-bucket-name: avatar

4
src/test/java/org/ycloud/aipan/AmazonS3ClientTests.java

@ -51,7 +51,7 @@ class AmazonS3ClientTests {
*/ */
@Test @Test
public void testDeleteBucket() { public void testDeleteBucket() {
String bucketName = "tjcz-app"; String bucketName = "forward-tech";
amazonS3Client.deleteBucket(bucketName); amazonS3Client.deleteBucket(bucketName);
} }
@ -93,7 +93,7 @@ class AmazonS3ClientTests {
*/ */
@Test @Test
public void testUploadFile2() { public void testUploadFile2() {
amazonS3Client.putObject("ai-pan", "test2.txt", new File("/Users/xdclass/Desktop/dpan.sql")); amazonS3Client.putObject("ai-pan", "test2.txt", new File("D:\\IdeaProjects\\learn\\ycloud-aipan\\doc\\ycloud-pan.sql"));
} }
/** /**

Loading…
Cancel
Save