Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
Y
yd-oss
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
xingmin
yd-oss
Commits
c5866e47
Commit
c5866e47
authored
Mar 18, 2026
by
zhangxingmin
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'origin/dev' into prod
parents
a26c6db3
35a8bfc3
Show whitespace changes
Inline
Side-by-side
Showing
42 changed files
with
1184 additions
and
483 deletions
+1184
-483
oss_sync.sh
+21
-0
yd-oss-api/Dockerfile
+2
-1
yd-oss-api/src/main/java/com/yd/oss/api/controller/ApiOssController.java
+2
-2
yd-oss-api/src/main/java/com/yd/oss/api/controller/ApiOssFileController.java
+2
-2
yd-oss-api/src/main/java/com/yd/oss/api/controller/ApiOssStsController.java
+46
-0
yd-oss-api/src/main/java/com/yd/oss/api/service/ApiOssFileService.java
+1
-1
yd-oss-api/src/main/java/com/yd/oss/api/service/ApiOssService.java
+1
-1
yd-oss-api/src/main/java/com/yd/oss/api/service/ApiOssStsService.java
+12
-0
yd-oss-api/src/main/java/com/yd/oss/api/service/impl/ApiExcelServiceImpl.java
+19
-5
yd-oss-api/src/main/java/com/yd/oss/api/service/impl/ApiOssFileServiceImpl.java
+13
-4
yd-oss-api/src/main/java/com/yd/oss/api/service/impl/ApiOssServiceImpl.java
+3
-6
yd-oss-api/src/main/java/com/yd/oss/api/service/impl/ApiOssStsServiceImpl.java
+236
-0
yd-oss-api/yd-oss-api.iml
+13
-9
yd-oss-feign/src/main/java/com/yd/oss/feign/client/ApiOssFeignClient.java
+4
-2
yd-oss-feign/src/main/java/com/yd/oss/feign/client/ApiOssFileFeignClient.java
+2
-1
yd-oss-feign/src/main/java/com/yd/oss/feign/client/ApiOssStsFeignClient.java
+35
-0
yd-oss-feign/src/main/java/com/yd/oss/feign/dto/ApiOssFileDto.java
+23
-0
yd-oss-feign/src/main/java/com/yd/oss/feign/fallback/ApiOssFeignFallbackFactory.java
+1
-1
yd-oss-feign/src/main/java/com/yd/oss/feign/fallback/ApiOssFileFeignFallbackFactory.java
+1
-1
yd-oss-feign/src/main/java/com/yd/oss/feign/fallback/ApiOssStsFeignFallbackFactory.java
+33
-0
yd-oss-feign/src/main/java/com/yd/oss/feign/request/ApiBatchSaveFilesRequest.java
+57
-0
yd-oss-feign/src/main/java/com/yd/oss/feign/request/ApiOssExportAppointmentExcelRequest.java
+5
-0
yd-oss-feign/src/main/java/com/yd/oss/feign/request/ApiUploadFileRequest.java
+5
-0
yd-oss-feign/src/main/java/com/yd/oss/feign/response/ApiBatchSaveFilesResponse.java
+11
-0
yd-oss-feign/src/main/java/com/yd/oss/feign/response/ApiGetStsTokenResponse.java
+26
-0
yd-oss-feign/src/main/java/com/yd/oss/feign/response/ApiOssFileResponse.java
+27
-0
yd-oss-service/pom.xml
+12
-0
yd-oss-service/src/main/java/com/yd/oss/service/config/DynamicOssClientProxy.java
+32
-0
yd-oss-service/src/main/java/com/yd/oss/service/config/OssClientFactory.java
+55
-0
yd-oss-service/src/main/java/com/yd/oss/service/config/OssConfig.java
+7
-0
yd-oss-service/src/main/java/com/yd/oss/service/dto/OssUploadFileReqDto.java
+5
-0
yd-oss-service/src/main/java/com/yd/oss/service/model/OssFile.java
+12
-0
yd-oss-service/src/main/java/com/yd/oss/service/model/OssProvider.java
+12
-0
yd-oss-service/src/main/java/com/yd/oss/service/service/AppointmentExcelService.java
+2
-1
yd-oss-service/src/main/java/com/yd/oss/service/service/IOssProviderService.java
+4
-0
yd-oss-service/src/main/java/com/yd/oss/service/service/OssService.java
+9
-2
yd-oss-service/src/main/java/com/yd/oss/service/service/impl/AliYunOssServiceImpl.java
+310
-431
yd-oss-service/src/main/java/com/yd/oss/service/service/impl/AppointmentExcelServiceImpl.java
+4
-3
yd-oss-service/src/main/java/com/yd/oss/service/service/impl/ExcelExportServiceImpl.java
+2
-1
yd-oss-service/src/main/java/com/yd/oss/service/service/impl/OssProviderServiceImpl.java
+30
-0
yd-oss-service/src/main/java/com/yd/oss/service/utils/OssUtils.java
+74
-0
yd-oss-service/yd-oss-service.iml
+13
-9
No files found.
oss_sync.sh
0 → 100644
View file @
c5866e47
#!/bin/bash
# 源端(使用默认配置,无需凭证)
SRC_BUCKET
=
"yd-ali-oss"
# 目标端(香港)
DST_BUCKET
=
"csf-hk"
DST_ENDPOINT
=
"oss-cn-hongkong.aliyuncs.com"
DST_ACCESS_KEY_ID
=
"LTAI5tHS7WBNxN7CwKcWC1Jh"
DST_ACCESS_KEY_SECRET
=
"GaJi5KHqcLOf2lBIFlPKBKDKCECUjo"
# 同步选项
UPDATE_FLAG
=
"--update"
# 只同步新增和修改过的文件
LOG_FILE
=
"/root/oss_sync.log"
echo
"
$(
date
'+%Y-%m-%d %H:%M:%S'
)
- Start sync"
>>
${
LOG_FILE
}
ossutil sync oss://
${
SRC_BUCKET
}
/jpg/ oss://
${
DST_BUCKET
}
/pc/prod/
\
-e
${
DST_ENDPOINT
}
-i
${
DST_ACCESS_KEY_ID
}
-k
${
DST_ACCESS_KEY_SECRET
}
\
${
UPDATE_FLAG
}
>>
${
LOG_FILE
}
2>&1
echo
"
$(
date
'+%Y-%m-%d %H:%M:%S'
)
- Sync finished"
>>
${
LOG_FILE
}
\ No newline at end of file
yd-oss-api/Dockerfile
View file @
c5866e47
...
...
@@ -36,5 +36,5 @@ FROM base-builder
COPY
target/yd-oss-api-1.0-SNAPSHOT-exec.jar /home/app/yd-oss-api.jar
# 执行命令启动jar,并设置JVM内存参数
ENTRYPOINT
["java", "-Xmx
256m", "-Xms128
m", "-jar", "/home/app/yd-oss-api.jar"]
ENTRYPOINT
["java", "-Xmx
1024m", "-Xms512
m", "-jar", "/home/app/yd-oss-api.jar"]
EXPOSE
9106
\ No newline at end of file
yd-oss-api/src/main/java/com/yd/oss/api/controller/ApiOssController.java
View file @
c5866e47
...
...
@@ -35,8 +35,8 @@ public class ApiOssController implements ApiOssFeignClient {
* @return
*/
@Override
public
Result
<
ApiUploadResponse
>
uploadFile
(
MultipartFile
file
)
{
return
apiOssService
.
uploadFile
(
file
,
""
,
""
,
""
);
public
Result
<
ApiUploadResponse
>
uploadFile
(
MultipartFile
file
,
String
projectBizId
)
{
return
apiOssService
.
uploadFile
(
file
,
""
,
""
,
""
,
projectBizId
);
}
/**
...
...
yd-oss-api/src/main/java/com/yd/oss/api/controller/ApiOssFileController.java
View file @
c5866e47
...
...
@@ -43,7 +43,7 @@ public class ApiOssFileController implements ApiOssFileFeignClient {
* @return
*/
@Override
public
Result
del
(
String
fileBizId
)
{
return
apiOssFileService
.
del
(
fileBizId
);
public
Result
del
(
String
fileBizId
,
String
projectBizId
)
{
return
apiOssFileService
.
del
(
fileBizId
,
projectBizId
);
}
}
yd-oss-api/src/main/java/com/yd/oss/api/controller/ApiOssStsController.java
0 → 100644
View file @
c5866e47
package
com
.
yd
.
oss
.
api
.
controller
;
import
com.yd.common.result.Result
;
import
com.yd.oss.api.service.ApiOssStsService
;
import
com.yd.oss.feign.client.ApiOssStsFeignClient
;
import
com.yd.oss.feign.request.ApiBatchSaveFilesRequest
;
import
com.yd.oss.feign.response.ApiBatchSaveFilesResponse
;
import
com.yd.oss.feign.response.ApiGetStsTokenResponse
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.validation.annotation.Validated
;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
org.springframework.web.bind.annotation.RestController
;
/**
* OSS-分片接口信息
*
* @author zxm
* @since 2025-07-31
*/
@RestController
@RequestMapping
(
"/sts"
)
@Validated
public
class
ApiOssStsController
implements
ApiOssStsFeignClient
{
@Autowired
private
ApiOssStsService
apiOssStsService
;
/**
* 获取STS凭证
* @return
*/
public
Result
<
ApiGetStsTokenResponse
>
getStsToken
(
String
projectBizId
){
return
apiOssStsService
.
getStsToken
(
projectBizId
);
}
/**
* 批量保存文件列表
* @return
*/
@Override
public
Result
<
ApiBatchSaveFilesResponse
>
batchSaveFiles
(
ApiBatchSaveFilesRequest
request
)
{
return
apiOssStsService
.
batchSaveFiles
(
request
);
}
}
\ No newline at end of file
yd-oss-api/src/main/java/com/yd/oss/api/service/ApiOssFileService.java
View file @
c5866e47
...
...
@@ -11,7 +11,7 @@ import java.util.List;
public
interface
ApiOssFileService
{
Result
<
List
<
ApiOssFileListResponse
>>
list
(
ApiOssFileListRequest
request
);
Result
del
(
String
fileBizId
);
Result
del
(
String
fileBizId
,
String
projectBizId
);
Result
updateByMaterial
(
List
<
RelObjectMaterial
>
relObjectMaterialList
,
List
<
ApiRelMaterialDto
>
materialDtoList
);
...
...
yd-oss-api/src/main/java/com/yd/oss/api/service/ApiOssService.java
View file @
c5866e47
...
...
@@ -11,7 +11,7 @@ import javax.servlet.http.HttpServletResponse;
import
java.util.List
;
public
interface
ApiOssService
{
Result
<
ApiUploadResponse
>
uploadFile
(
MultipartFile
file
,
String
bucket
,
String
provider
,
String
uploadUser
);
Result
<
ApiUploadResponse
>
uploadFile
(
MultipartFile
file
,
String
bucket
,
String
provider
,
String
uploadUser
,
String
projectBizId
);
Result
<
ApiUploadResponse
>
uploadFileBody
(
MultipartFile
file
,
ApiUploadFileRequest
request
);
...
...
yd-oss-api/src/main/java/com/yd/oss/api/service/ApiOssStsService.java
0 → 100644
View file @
c5866e47
package
com
.
yd
.
oss
.
api
.
service
;
import
com.yd.common.result.Result
;
import
com.yd.oss.feign.request.ApiBatchSaveFilesRequest
;
import
com.yd.oss.feign.response.ApiBatchSaveFilesResponse
;
import
com.yd.oss.feign.response.ApiGetStsTokenResponse
;
public
interface
ApiOssStsService
{
Result
<
ApiGetStsTokenResponse
>
getStsToken
(
String
projectBizId
);
Result
<
ApiBatchSaveFilesResponse
>
batchSaveFiles
(
ApiBatchSaveFilesRequest
request
);
}
yd-oss-api/src/main/java/com/yd/oss/api/service/impl/ApiExcelServiceImpl.java
View file @
c5866e47
package
com
.
yd
.
oss
.
api
.
service
.
impl
;
import
com.aliyun.oss.OSS
;
import
com.yd.common.exception.BusinessException
;
import
com.yd.common.result.Result
;
import
com.yd.oss.api.service.ApiExcelService
;
...
...
@@ -10,10 +11,9 @@ import com.yd.oss.feign.response.ApiOssExportAppointmentExcelResponse;
import
com.yd.oss.feign.dto.ExportParam
;
import
com.yd.oss.feign.dto.ExportResult
;
import
com.yd.oss.feign.result.ImportResult
;
import
com.yd.oss.service.service.AppointmentExcelService
;
import
com.yd.oss.service.service.ExcelExportService
;
import
com.yd.oss.service.service.ExcelImportService
;
import
com.yd.oss.service.service.ExcelParserService
;
import
com.yd.oss.service.config.OssClientFactory
;
import
com.yd.oss.service.model.OssProvider
;
import
com.yd.oss.service.service.*
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Service
;
...
...
@@ -41,6 +41,12 @@ public class ApiExcelServiceImpl implements ApiExcelService {
@Autowired
private
ExcelImportService
excelImportService
;
@Autowired
private
OssClientFactory
ossClientFactory
;
@Autowired
private
IOssProviderService
ossProviderService
;
/**
* 导出excel-预约信息
* @param request
...
...
@@ -49,9 +55,17 @@ public class ApiExcelServiceImpl implements ApiExcelService {
@Override
public
Result
<
ApiOssExportAppointmentExcelResponse
>
exportAppointment
(
ApiOssExportAppointmentExcelRequest
request
)
{
ApiOssExportAppointmentExcelResponse
response
=
new
ApiOssExportAppointmentExcelResponse
();
// 根据项目ID获取服务商信息
OssProvider
provider
=
ossProviderService
.
getProviderByProjectId
(
request
.
getProjectBizId
());
if
(
provider
==
null
)
{
log
.
error
(
"未找到项目对应的OSS服务商,projectBizId={}"
,
request
.
getProjectBizId
());
return
Result
.
fail
(
"未找到对应的OSS服务商配置"
);
}
OSS
tempClient
=
ossClientFactory
.
createOssClient
(
provider
);
String
url
=
appointmentExcelService
.
exportAppointment
(
request
.
getData
(),
request
.
getTemplateType
(),
request
.
getAppointmentBizId
());
request
.
getAppointmentBizId
(),
request
.
getProjectBizId
());
response
.
setUrl
(
url
);
return
Result
.
success
(
response
);
}
...
...
yd-oss-api/src/main/java/com/yd/oss/api/service/impl/ApiOssFileServiceImpl.java
View file @
c5866e47
package
com
.
yd
.
oss
.
api
.
service
.
impl
;
import
com.yd.auth.core.dto.AuthUserDto
;
import
com.yd.auth.core.utils.SecurityUtil
;
import
com.yd.common.enums.CommonEnum
;
import
com.yd.common.enums.ResultCode
;
import
com.yd.common.exception.BusinessException
;
...
...
@@ -12,6 +14,7 @@ import com.yd.oss.service.dto.OssFileDto;
import
com.yd.oss.service.model.OssFile
;
import
com.yd.oss.service.model.RelObjectMaterial
;
import
com.yd.oss.service.service.IOssFileService
;
import
com.yd.oss.service.service.OssService
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.beans.BeanUtils
;
import
org.springframework.beans.factory.annotation.Autowired
;
...
...
@@ -28,6 +31,9 @@ public class ApiOssFileServiceImpl implements ApiOssFileService {
@Autowired
private
IOssFileService
iOssFileService
;
@Autowired
private
OssService
ossService
;
/**
* 列表查询-文件元数据信息
* @param request
...
...
@@ -45,10 +51,13 @@ public class ApiOssFileServiceImpl implements ApiOssFileService {
* @return
*/
@Override
public
Result
del
(
String
fileBizId
)
{
Result
<
OssFile
>
result
=
checkOssFileIsExist
(
fileBizId
);
OssFile
ossFile
=
result
.
getData
();
iOssFileService
.
removeById
(
ossFile
.
getId
());
public
Result
del
(
String
fileBizId
,
String
projectBizId
)
{
// 获取当前操作人
AuthUserDto
authUser
=
SecurityUtil
.
getCurrentLoginUser
();
String
operator
=
authUser
!=
null
?
authUser
.
getUsername
()
:
"system"
;
// 调用OSS服务删除文件(包含OSS删除和数据库物理删除)
ossService
.
deleteFileByBizId
(
fileBizId
,
operator
);
return
Result
.
success
();
}
...
...
yd-oss-api/src/main/java/com/yd/oss/api/service/impl/ApiOssServiceImpl.java
View file @
c5866e47
package
com
.
yd
.
oss
.
api
.
service
.
impl
;
import
com.alibaba.cloud.commons.lang.StringUtils
;
import
com.yd.common.exception.BusinessException
;
import
com.yd.common.result.Result
;
import
com.yd.oss.api.service.ApiOssService
;
import
com.yd.oss.feign.request.ApiUploadFileRequest
;
...
...
@@ -42,17 +43,13 @@ public class ApiOssServiceImpl implements ApiOssService {
* @return
*/
@Override
public
Result
<
ApiUploadResponse
>
uploadFile
(
MultipartFile
file
,
String
bucket
,
String
provider
,
String
uploadUser
)
{
public
Result
<
ApiUploadResponse
>
uploadFile
(
MultipartFile
file
,
String
bucket
,
String
provider
,
String
uploadUser
,
String
projectBizId
)
{
ApiUploadResponse
response
=
new
ApiUploadResponse
();
try
{
// 如果指定了提供商,则切换
if
(
StringUtils
.
isNotBlank
(
provider
))
{
ossService
.
switchProvider
(
provider
);
}
// 上传文件
OssUploadFileResDto
ossUploadFileDto
=
ossService
.
uploadFile
(
file
.
getInputStream
(),
file
.
getOriginalFilename
(),
bucket
,
uploadUser
,
FileUtil
.
getFileType
(
file
.
getOriginalFilename
()));
bucket
,
uploadUser
,
FileUtil
.
getFileType
(
file
.
getOriginalFilename
())
,
projectBizId
);
// 获取上传结果(包含文件信息和访问URL)
UploadResult
result
=
ossService
.
getUploadResult
(
ossUploadFileDto
.
getFileKey
(),
Duration
.
ofHours
(
1
));
...
...
yd-oss-api/src/main/java/com/yd/oss/api/service/impl/ApiOssStsServiceImpl.java
0 → 100644
View file @
c5866e47
package
com
.
yd
.
oss
.
api
.
service
.
impl
;
import
com.aliyun.oss.OSS
;
import
com.aliyuncs.DefaultAcsClient
;
import
com.aliyuncs.IAcsClient
;
import
com.aliyuncs.exceptions.ClientException
;
import
com.aliyuncs.profile.DefaultProfile
;
import
com.aliyuncs.sts.model.v20150401.AssumeRoleRequest
;
import
com.aliyuncs.sts.model.v20150401.AssumeRoleResponse
;
import
com.yd.auth.core.dto.AuthUserDto
;
import
com.yd.auth.core.utils.SecurityUtil
;
import
com.yd.common.enums.CommonEnum
;
import
com.yd.common.result.Result
;
import
com.yd.common.utils.RandomStringGenerator
;
import
com.yd.oss.api.service.ApiOssStsService
;
import
com.yd.oss.service.config.OssClientFactory
;
import
com.yd.oss.service.model.OssProvider
;
import
com.yd.oss.service.service.IOssProviderService
;
import
com.yd.oss.service.utils.OssUtils
;
import
com.yd.oss.feign.dto.ApiOssFileDto
;
import
com.yd.oss.feign.request.ApiBatchSaveFilesRequest
;
import
com.yd.oss.feign.response.ApiBatchSaveFilesResponse
;
import
com.yd.oss.feign.response.ApiGetStsTokenResponse
;
import
com.yd.oss.feign.response.ApiOssFileResponse
;
import
com.yd.oss.service.model.OssFile
;
import
com.yd.oss.service.service.IOssFileService
;
import
lombok.extern.slf4j.Slf4j
;
import
org.apache.commons.collections4.CollectionUtils
;
import
org.apache.commons.io.FilenameUtils
;
import
org.apache.commons.lang3.StringUtils
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.stereotype.Service
;
import
org.springframework.transaction.annotation.Transactional
;
import
java.net.MalformedURLException
;
import
java.net.URL
;
import
java.time.LocalDateTime
;
import
java.util.ArrayList
;
import
java.util.List
;
@Slf4j
@Service
public
class
ApiOssStsServiceImpl
implements
ApiOssStsService
{
@Value
(
"${aliyun.oss.role-arn:acs:ram::1164861558430519:role/oss-upload-role}"
)
private
String
roleArn
;
// 注入最大文件大小配置,默认100MB
@Value
(
"${aliyun.oss.max-size:104857600}"
)
private
Long
maxSize
;
@Autowired
private
IOssProviderService
ossProviderService
;
@Autowired
private
IOssFileService
iOssFileService
;
@Autowired
private
OssUtils
ossUtils
;
@Autowired
private
OssClientFactory
ossClientFactory
;
// 如果需要执行OSS操作时使用
/**
* 获取STS临时凭证
* @param projectBizId 项目业务ID,用于确定使用的OSS服务商
* @return STS凭证响应
*/
@Override
public
Result
<
ApiGetStsTokenResponse
>
getStsToken
(
String
projectBizId
)
{
// 根据项目ID获取服务商信息
OssProvider
provider
=
ossProviderService
.
getProviderByProjectId
(
projectBizId
);
if
(
provider
==
null
)
{
log
.
error
(
"未找到项目对应的OSS服务商,projectBizId={}"
,
projectBizId
);
return
Result
.
fail
(
"未找到对应的OSS服务商配置"
);
}
String
region
=
provider
.
getRegion
();
String
accessKeyId
=
provider
.
getAccessKey
();
String
accessKeySecret
=
provider
.
getSecretKey
();
String
bucket
=
provider
.
getBucketName
();
String
endpoint
=
provider
.
getEndpoint
();
// 检查bucket是否存在
// 如果需要检查,可以用ossClientFactory创建临时客户端执行操作,然后关闭
OSS
tempClient
=
ossClientFactory
.
createOssClient
(
provider
);
try
{
if
(!
tempClient
.
doesBucketExist
(
bucket
))
{
log
.
warn
(
"当前服务商的桶 {} 不存在,请确认配置"
,
bucket
);
}
}
finally
{
tempClient
.
shutdown
();
}
// 构建STS客户端
DefaultProfile
profile
=
DefaultProfile
.
getProfile
(
region
,
accessKeyId
,
accessKeySecret
);
IAcsClient
client
=
new
DefaultAcsClient
(
profile
);
// 构建请求
AssumeRoleRequest
request
=
new
AssumeRoleRequest
();
request
.
setRoleArn
(
roleArn
);
request
.
setRoleSessionName
(
"vue-upload-session"
);
request
.
setDurationSeconds
(
3600L
);
try
{
AssumeRoleResponse
response
=
client
.
getAcsResponse
(
request
);
if
(
response
==
null
||
response
.
getCredentials
()
==
null
)
{
return
Result
.
fail
(
"获取STS凭证失败:返回凭证为空"
);
}
AssumeRoleResponse
.
Credentials
credentials
=
response
.
getCredentials
();
ApiGetStsTokenResponse
tokenResponse
=
new
ApiGetStsTokenResponse
();
tokenResponse
.
setAccessKeyId
(
credentials
.
getAccessKeyId
());
tokenResponse
.
setAccessKeySecret
(
credentials
.
getAccessKeySecret
());
tokenResponse
.
setStsToken
(
credentials
.
getSecurityToken
());
tokenResponse
.
setRegion
(
region
);
tokenResponse
.
setBucket
(
bucket
);
tokenResponse
.
setEndpoint
(
endpoint
);
tokenResponse
.
setMaxSize
(
maxSize
);
// 获取分片文件路径的前缀
String
filePrefix
=
ossUtils
.
getShardFilePrefix
(
projectBizId
,
""
);
tokenResponse
.
setFilePrefix
(
filePrefix
);
return
Result
.
success
(
tokenResponse
);
}
catch
(
ClientException
e
)
{
log
.
error
(
"获取STS凭证失败"
,
e
);
return
Result
.
fail
(
"获取STS凭证失败: "
+
e
.
getMessage
());
}
}
/**
* 批量保存文件列表(仅保存元数据,不涉及OSS操作)
*
* @param request 批量保存请求
* @return 保存结果
*/
@Override
@Transactional
(
rollbackFor
=
Exception
.
class
)
public
Result
<
ApiBatchSaveFilesResponse
>
batchSaveFiles
(
ApiBatchSaveFilesRequest
request
)
{
// 根据 projectBizId 获取服务商信息(用于填充providerBizId和bucketName)
OssProvider
provider
=
ossProviderService
.
getProviderByProjectId
(
request
.
getProjectBizId
());
if
(
provider
==
null
)
{
log
.
error
(
"批量保存文件时未找到服务商配置,projectBizId={}"
,
request
.
getProjectBizId
());
return
Result
.
fail
(
"未找到对应的OSS服务商配置"
);
}
String
providerBizId
=
provider
.
getProviderBizId
();
String
bucketName
=
provider
.
getBucketName
();
// 获取当前登录用户信息
AuthUserDto
authUserDto
=
SecurityUtil
.
getCurrentLoginUser
();
String
userId
=
authUserDto
.
getUserBizId
();
String
userName
=
authUserDto
.
getUsername
();
List
<
OssFile
>
saveOssFileList
=
new
ArrayList
<>();
List
<
ApiOssFileResponse
>
fileResponses
=
new
ArrayList
<>();
// 遍历处理文件列表
for
(
ApiOssFileDto
fileDto
:
request
.
getApiOssFileDtoList
())
{
try
{
// 从完整 URL 中提取 fileKey(相对路径)
String
fileUrl
=
fileDto
.
getFileUrl
();
if
(
StringUtils
.
isBlank
(
fileUrl
))
{
log
.
warn
(
"文件URL为空,跳过:{}"
,
fileDto
);
continue
;
}
URL
url
=
new
URL
(
fileUrl
);
String
path
=
url
.
getPath
();
String
fileKey
=
path
.
startsWith
(
"/"
)
?
path
.
substring
(
1
)
:
path
;
// 生成文件业务ID
String
fileBizId
=
RandomStringGenerator
.
generateBizId16
(
CommonEnum
.
UID_TYPE_OSS_FILE
.
getCode
());
// 获取文件类型(扩展名)
String
originalName
=
fileDto
.
getFileName
();
String
fileType
=
FilenameUtils
.
getExtension
(
originalName
);
if
(
StringUtils
.
isBlank
(
fileType
))
{
fileType
=
FilenameUtils
.
getExtension
(
fileKey
);
}
// 构建实体
OssFile
file
=
new
OssFile
();
file
.
setTenantBizId
(
request
.
getTenantBizId
());
file
.
setProjectBizId
(
request
.
getProjectBizId
());
file
.
setFileBizId
(
fileBizId
);
file
.
setObjectType
(
request
.
getObjectType
());
file
.
setObjectTableName
(
request
.
getObjectTableName
());
file
.
setObjectName
(
request
.
getObjectName
());
file
.
setObjectBizId
(
request
.
getObjectBizId
());
file
.
setFileKey
(
fileKey
);
file
.
setOriginalName
(
originalName
);
file
.
setFileSize
(
fileDto
.
getFileSize
());
file
.
setFileType
(
fileType
);
file
.
setProviderBizId
(
providerBizId
);
file
.
setBucketName
(
bucketName
);
file
.
setUploadTime
(
LocalDateTime
.
now
());
file
.
setUploadUser
(
userId
);
file
.
setCreatorId
(
userId
);
file
.
setCreatorName
(
userName
);
file
.
setUpdaterId
(
userId
);
file
.
setCreateTime
(
LocalDateTime
.
now
());
file
.
setUpdateTime
(
LocalDateTime
.
now
());
file
.
setIsDeleted
(
0
);
saveOssFileList
.
add
(
file
);
// 构建响应对象(直接使用传入的完整URL)
ApiOssFileResponse
ossFileResponse
=
new
ApiOssFileResponse
();
ossFileResponse
.
setFileBizId
(
file
.
getFileBizId
());
ossFileResponse
.
setFileName
(
file
.
getOriginalName
());
ossFileResponse
.
setFileSize
(
file
.
getFileSize
());
ossFileResponse
.
setFileUrl
(
fileDto
.
getFileUrl
());
// 设置完整URL
fileResponses
.
add
(
ossFileResponse
);
}
catch
(
MalformedURLException
e
)
{
log
.
error
(
"文件URL格式错误: {}"
,
fileDto
.
getFileUrl
(),
e
);
return
Result
.
fail
(
"文件URL格式错误: "
+
fileDto
.
getFileUrl
());
}
catch
(
Exception
e
)
{
log
.
error
(
"保存文件记录失败: {}"
,
fileDto
,
e
);
return
Result
.
fail
(
"保存文件记录失败: "
+
e
.
getMessage
());
}
}
// 批量保存
if
(
CollectionUtils
.
isNotEmpty
(
saveOssFileList
))
{
iOssFileService
.
saveOrUpdateBatch
(
saveOssFileList
);
// 构建响应
ApiBatchSaveFilesResponse
response
=
new
ApiBatchSaveFilesResponse
();
response
.
setFileResponses
(
fileResponses
);
return
Result
.
success
(
response
);
}
return
Result
.
success
();
}
}
\ No newline at end of file
yd-oss-api/yd-oss-api.iml
View file @
c5866e47
...
...
@@ -84,7 +84,6 @@
<orderEntry
type=
"library"
name=
"Maven: org.springframework.cloud:spring-cloud-starter:3.1.1"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: org.springframework.security:spring-security-rsa:1.0.10.RELEASE"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: org.bouncycastle:bcpkix-jdk15on:1.68"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: org.bouncycastle:bcprov-jdk15on:1.69"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: com.fasterxml.jackson.core:jackson-databind:2.13.2"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: com.fasterxml.jackson.core:jackson-core:2.13.2"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: com.fasterxml.jackson.core:jackson-annotations:2.13.2"
level=
"project"
/>
...
...
@@ -135,8 +134,6 @@
<orderEntry
type=
"library"
name=
"Maven: org.springdoc:springdoc-openapi-webmvc-core:1.7.0"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: org.springdoc:springdoc-openapi-common:1.7.0"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: io.swagger.core.v3:swagger-core:2.2.9"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: jakarta.xml.bind:jakarta.xml.bind-api:2.3.3"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: jakarta.activation:jakarta.activation-api:1.2.2"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: io.swagger.core.v3:swagger-annotations:2.2.9"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: io.swagger.core.v3:swagger-models:2.2.9"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: org.webjars:swagger-ui:4.18.2"
level=
"project"
/>
...
...
@@ -196,22 +193,30 @@
<orderEntry
type=
"library"
name=
"Maven: io.github.openfeign:feign-slf4j:11.8"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: com.aliyun.oss:aliyun-sdk-oss:3.15.1"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: org.apache.httpcomponents:httpclient:4.5.13"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: org.apache.httpcomponents:httpcore:4.4.15"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: org.jdom:jdom2:2.0.6.1"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: org.codehaus.jettison:jettison:1.1"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: stax:stax-api:1.0.1"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: com.aliyun:aliyun-java-sdk-core:4.5.10"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: com.aliyun:aliyun-java-sdk-ram:3.1.0"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: com.aliyun:aliyun-java-sdk-kms:2.11.0"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: com.aliyun:aliyun-java-sdk-sts:3.0.0"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: com.aliyun:aliyun-java-sdk-core:4.6.0"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: com.google.code.gson:gson:2.8.9"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: org.apache.httpcomponents:httpcore:4.4.15"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: commons-logging:commons-logging:1.2"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: org.apache.commons:commons-lang3:3.14.0"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: javax.xml.bind:jaxb-api:2.3.1"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: javax.activation:javax.activation-api:1.2.0"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: org.jacoco:org.jacoco.agent:runtime:0.8.5"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: org.glassfish.jaxb:jaxb-runtime:2.3.6"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: jakarta.xml.bind:jakarta.xml.bind-api:2.3.3"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: org.glassfish.jaxb:txw2:2.3.6"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: com.sun.istack:istack-commons-runtime:3.0.12"
level=
"project"
/>
<orderEntry
type=
"library"
scope=
"RUNTIME"
name=
"Maven: com.sun.activation:jakarta.activation:1.2.2"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: org.bouncycastle:bcprov-jdk15on:1.69"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: org.jacoco:org.jacoco.agent:runtime:0.8.7"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: org.ini4j:ini4j:0.5.4"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: io.opentracing:opentracing-api:0.33.0"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: io.opentracing:opentracing-util:0.33.0"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: io.opentracing:opentracing-noop:0.33.0"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: com.aliyun:aliyun-java-sdk-ram:3.1.0"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: com.aliyun:aliyun-java-sdk-kms:2.11.0"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: org.apache.tomcat.embed:tomcat-embed-core:9.0.60"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: org.apache.tomcat:tomcat-annotations-api:9.0.60"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: com.documents4j:documents4j-local:1.1.12"
level=
"project"
/>
...
...
@@ -237,7 +242,6 @@
<orderEntry
type=
"library"
name=
"Maven: org.apache.xmlbeans:xmlbeans:5.1.1"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: cn.afterturn:easypoi-base:4.4.0"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: org.apache.poi:poi-ooxml-schemas:4.1.1"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: org.apache.commons:commons-lang3:3.14.0"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: ognl:ognl:3.2.6"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: org.javassist:javassist:3.20.0-GA"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: javax.validation:validation-api:2.0.1.Final"
level=
"project"
/>
...
...
yd-oss-feign/src/main/java/com/yd/oss/feign/client/ApiOssFeignClient.java
View file @
c5866e47
...
...
@@ -11,6 +11,7 @@ import org.springframework.http.MediaType;
import
org.springframework.web.bind.annotation.*
;
import
org.springframework.web.multipart.MultipartFile
;
import
javax.validation.constraints.NotBlank
;
import
java.util.List
;
/**
...
...
@@ -24,8 +25,9 @@ public interface ApiOssFeignClient {
* @param file 上传的文件
* @return
*/
@PostMapping
(
"/upload"
)
Result
<
ApiUploadResponse
>
uploadFile
(
@RequestParam
(
"file"
)
MultipartFile
file
);
@PostMapping
(
value
=
"/upload"
,
consumes
=
MediaType
.
MULTIPART_FORM_DATA_VALUE
)
Result
<
ApiUploadResponse
>
uploadFile
(
@RequestPart
(
"file"
)
MultipartFile
file
,
@RequestParam
(
value
=
"projectBizId"
,
required
=
false
)
String
projectBizId
);
/**
* 上传文件 - body入参方式(新,推荐)
...
...
yd-oss-feign/src/main/java/com/yd/oss/feign/client/ApiOssFileFeignClient.java
View file @
c5866e47
...
...
@@ -33,6 +33,7 @@ public interface ApiOssFileFeignClient {
* @return
*/
@DeleteMapping
(
"/del"
)
Result
del
(
@NotBlank
(
message
=
"文件元数据表唯一业务ID不能为空"
)
@RequestParam
(
value
=
"fileBizId"
)
String
fileBizId
);
Result
del
(
@NotBlank
(
message
=
"文件元数据表唯一业务ID不能为空"
)
@RequestParam
(
value
=
"fileBizId"
)
String
fileBizId
,
@RequestParam
(
"projectBizId"
)
String
projectBizId
);
}
yd-oss-feign/src/main/java/com/yd/oss/feign/client/ApiOssStsFeignClient.java
0 → 100644
View file @
c5866e47
package
com
.
yd
.
oss
.
feign
.
client
;
import
com.yd.common.result.Result
;
import
com.yd.oss.feign.fallback.ApiOssStsFeignFallbackFactory
;
import
com.yd.oss.feign.request.ApiBatchSaveFilesRequest
;
import
com.yd.oss.feign.response.ApiBatchSaveFilesResponse
;
import
com.yd.oss.feign.response.ApiGetStsTokenResponse
;
import
org.springframework.cloud.openfeign.FeignClient
;
import
org.springframework.validation.annotation.Validated
;
import
org.springframework.web.bind.annotation.GetMapping
;
import
org.springframework.web.bind.annotation.PostMapping
;
import
org.springframework.web.bind.annotation.RequestBody
;
import
org.springframework.web.bind.annotation.RequestParam
;
/**
* OSS-分片服务信息Feign客户端
*/
@FeignClient
(
name
=
"yd-oss-api"
,
fallbackFactory
=
ApiOssStsFeignFallbackFactory
.
class
)
public
interface
ApiOssStsFeignClient
{
/**
* 获取STS凭证
* @param projectBizId
* @return
*/
@GetMapping
(
"/sts-token"
)
Result
<
ApiGetStsTokenResponse
>
getStsToken
(
@RequestParam
(
value
=
"projectBizId"
)
String
projectBizId
);
/**
* 批量保存文件列表
* @return
*/
@PostMapping
(
"/batch/save/files"
)
Result
<
ApiBatchSaveFilesResponse
>
batchSaveFiles
(
@Validated
@RequestBody
ApiBatchSaveFilesRequest
request
);
}
yd-oss-feign/src/main/java/com/yd/oss/feign/dto/ApiOssFileDto.java
0 → 100644
View file @
c5866e47
package
com
.
yd
.
oss
.
feign
.
dto
;
import
lombok.Data
;
@Data
public
class
ApiOssFileDto
{
/**
* 文件名(原始文件名)
*/
private
String
fileName
;
/**
* 文件大小
*/
private
Long
fileSize
;
/**
* 上传文件路径(完整路径)
*/
private
String
fileUrl
;
}
yd-oss-feign/src/main/java/com/yd/oss/feign/fallback/ApiOssFeignFallbackFactory.java
View file @
c5866e47
...
...
@@ -23,7 +23,7 @@ public class ApiOssFeignFallbackFactory implements FallbackFactory<ApiOssFeignCl
public
ApiOssFeignClient
create
(
Throwable
cause
)
{
return
new
ApiOssFeignClient
()
{
@Override
public
Result
<
ApiUploadResponse
>
uploadFile
(
MultipartFile
file
)
{
public
Result
<
ApiUploadResponse
>
uploadFile
(
MultipartFile
file
,
String
projectBizId
)
{
return
null
;
}
...
...
yd-oss-feign/src/main/java/com/yd/oss/feign/fallback/ApiOssFileFeignFallbackFactory.java
View file @
c5866e47
...
...
@@ -24,7 +24,7 @@ public class ApiOssFileFeignFallbackFactory implements FallbackFactory<ApiOssFil
}
@Override
public
Result
del
(
String
fileBizId
)
{
public
Result
del
(
String
fileBizId
,
String
projectBizId
)
{
return
null
;
}
};
...
...
yd-oss-feign/src/main/java/com/yd/oss/feign/fallback/ApiOssStsFeignFallbackFactory.java
0 → 100644
View file @
c5866e47
package
com
.
yd
.
oss
.
feign
.
fallback
;
import
com.yd.common.result.Result
;
import
com.yd.oss.feign.client.ApiOssStsFeignClient
;
import
com.yd.oss.feign.request.ApiBatchSaveFilesRequest
;
import
com.yd.oss.feign.response.ApiBatchSaveFilesResponse
;
import
com.yd.oss.feign.response.ApiGetStsTokenResponse
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.cloud.openfeign.FallbackFactory
;
import
org.springframework.stereotype.Component
;
import
org.springframework.web.bind.annotation.RequestParam
;
/**
* OSS服务信息Feign降级处理
*/
@Slf4j
@Component
public
class
ApiOssStsFeignFallbackFactory
implements
FallbackFactory
<
ApiOssStsFeignClient
>
{
@Override
public
ApiOssStsFeignClient
create
(
Throwable
cause
)
{
return
new
ApiOssStsFeignClient
()
{
@Override
public
Result
<
ApiGetStsTokenResponse
>
getStsToken
(
String
projectBizId
)
{
return
null
;
}
@Override
public
Result
<
ApiBatchSaveFilesResponse
>
batchSaveFiles
(
ApiBatchSaveFilesRequest
request
)
{
return
null
;
}
};
}
}
yd-oss-feign/src/main/java/com/yd/oss/feign/request/ApiBatchSaveFilesRequest.java
0 → 100644
View file @
c5866e47
package
com
.
yd
.
oss
.
feign
.
request
;
import
com.yd.oss.feign.dto.ApiOssFileDto
;
import
lombok.Data
;
import
javax.validation.constraints.NotBlank
;
import
javax.validation.constraints.NotEmpty
;
import
java.util.List
;
@Data
public
class
ApiBatchSaveFilesRequest
{
/**
* 所属租户ID(业务id)
*/
@NotBlank
(
message
=
"所属租户ID不能为空"
)
private
String
tenantBizId
;
/**
* 所属项目ID(业务id)
*/
@NotBlank
(
message
=
"所属项目ID不能为空"
)
private
String
projectBizId
;
/**
* 项目类型类型(默认pc)
*/
private
String
projectType
=
"pc"
;
/**
* 对象类型
*/
private
String
objectType
;
/**
* 对象所属表名(预约表、新单跟进表等)
*/
private
String
objectTableName
;
/**
* 对象名
*/
private
String
objectName
;
/**
* 对象业务ID
*/
@NotBlank
(
message
=
"对象业务ID不能为空"
)
private
String
objectBizId
;
/**
* 上传的文件对象列表
*/
@NotEmpty
(
message
=
"上传的文件对象列表不能为空"
)
private
List
<
ApiOssFileDto
>
apiOssFileDtoList
;
}
yd-oss-feign/src/main/java/com/yd/oss/feign/request/ApiOssExportAppointmentExcelRequest.java
View file @
c5866e47
...
...
@@ -23,4 +23,9 @@ public class ApiOssExportAppointmentExcelRequest {
* 预约信息主表唯一业务ID
*/
private
String
appointmentBizId
;
/**
* 项目ID
*/
private
String
projectBizId
;
}
yd-oss-feign/src/main/java/com/yd/oss/feign/request/ApiUploadFileRequest.java
View file @
c5866e47
...
...
@@ -8,6 +8,11 @@ import javax.validation.constraints.NotBlank;
public
class
ApiUploadFileRequest
{
/**
* 项目ID
*/
private
String
projectBizId
;
/**
* 对象类型
*/
private
String
objectType
;
...
...
yd-oss-feign/src/main/java/com/yd/oss/feign/response/ApiBatchSaveFilesResponse.java
0 → 100644
View file @
c5866e47
package
com
.
yd
.
oss
.
feign
.
response
;
import
lombok.Data
;
import
java.util.List
;
@Data
public
class
ApiBatchSaveFilesResponse
{
private
List
<
ApiOssFileResponse
>
fileResponses
;
}
yd-oss-feign/src/main/java/com/yd/oss/feign/response/ApiGetStsTokenResponse.java
0 → 100644
View file @
c5866e47
package
com
.
yd
.
oss
.
feign
.
response
;
import
lombok.Data
;
@Data
public
class
ApiGetStsTokenResponse
{
private
String
accessKeyId
;
private
String
accessKeySecret
;
private
String
stsToken
;
private
String
region
;
private
String
bucket
;
private
String
endpoint
;
private
Long
maxSize
;
/**
* 文件前缀
*/
private
String
filePrefix
;
}
yd-oss-feign/src/main/java/com/yd/oss/feign/response/ApiOssFileResponse.java
0 → 100644
View file @
c5866e47
package
com
.
yd
.
oss
.
feign
.
response
;
import
lombok.Data
;
@Data
public
class
ApiOssFileResponse
{
/**
* 文件元数据表唯一业务ID(不传值)
*/
private
String
fileBizId
;
/**
* 文件名(原始文件名)
*/
private
String
fileName
;
/**
* 文件大小
*/
private
Long
fileSize
;
/**
* 上传文件路径(完整路径)
*/
private
String
fileUrl
;
}
yd-oss-service/pom.xml
View file @
c5866e47
...
...
@@ -80,6 +80,18 @@
<groupId>
com.aliyun.oss
</groupId>
<artifactId>
aliyun-sdk-oss
</artifactId>
</dependency>
<!-- 阿里云 STS SDK -->
<dependency>
<groupId>
com.aliyun
</groupId>
<artifactId>
aliyun-java-sdk-sts
</artifactId>
<version>
3.0.0
</version>
</dependency>
<dependency>
<groupId>
com.aliyun
</groupId>
<artifactId>
aliyun-java-sdk-core
</artifactId>
<version>
4.6.0
</version>
</dependency>
<dependency>
<groupId>
org.apache.tomcat.embed
</groupId>
<artifactId>
tomcat-embed-core
</artifactId>
...
...
yd-oss-service/src/main/java/com/yd/oss/service/config/DynamicOssClientProxy.java
0 → 100644
View file @
c5866e47
//package com.yd.oss.service.config;
//
//import com.aliyun.oss.OSS;
//import com.yd.oss.service.service.OssService;
//
//import java.lang.reflect.InvocationHandler;
//import java.lang.reflect.Method;
//import java.lang.reflect.Proxy;
//
//public class DynamicOssClientProxy implements InvocationHandler {
// private final OssService ossService;
//
// public DynamicOssClientProxy(OssService ossService) {
// this.ossService = ossService;
// }
//
// public static OSS createProxy(OssService ossService) {
// return (OSS) Proxy.newProxyInstance(
// DynamicOssClientProxy.class.getClassLoader(),
// new Class[]{OSS.class},
// new DynamicOssClientProxy(ossService)
// );
// }
//
// @Override
// public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// // 每次方法调用都从 OssService 获取当前客户端
// OSS currentClient = ossService.getOssClient();
// return method.invoke(currentClient, args);
// }
//}
\ No newline at end of file
yd-oss-service/src/main/java/com/yd/oss/service/config/OssClientFactory.java
0 → 100644
View file @
c5866e47
package
com
.
yd
.
oss
.
service
.
config
;
import
com.aliyun.oss.OSS
;
import
com.aliyun.oss.OSSClientBuilder
;
import
com.yd.oss.service.model.OssProvider
;
import
com.yd.oss.service.service.IOssProviderService
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Component
;
@Component
public
class
OssClientFactory
{
@Autowired
private
IOssProviderService
ossProviderService
;
/**
* 根据服务商业务ID创建临时OSS客户端
* @param providerBizId 服务商业务ID
* @return OSS客户端(使用后必须调用shutdown())
*/
public
OSS
createOssClient
(
String
providerBizId
)
{
OssProvider
provider
=
ossProviderService
.
getProviderByBizId
(
providerBizId
);
return
new
OSSClientBuilder
().
build
(
provider
.
getEndpoint
(),
provider
.
getAccessKey
(),
provider
.
getSecretKey
()
);
}
/**
* 根据项目ID创建临时OSS客户端
* @param projectBizId 项目业务ID
* @return OSS客户端(使用后必须调用shutdown())
*/
public
OSS
createOssClientByProject
(
String
projectBizId
)
{
OssProvider
provider
=
ossProviderService
.
getProviderByProjectId
(
projectBizId
);
return
new
OSSClientBuilder
().
build
(
provider
.
getEndpoint
(),
provider
.
getAccessKey
(),
provider
.
getSecretKey
()
);
}
/**
* 直接根据OssProvider对象创建客户端(如果调用者已持有provider)
*/
public
OSS
createOssClient
(
OssProvider
provider
)
{
return
new
OSSClientBuilder
().
build
(
provider
.
getEndpoint
(),
provider
.
getAccessKey
(),
provider
.
getSecretKey
()
);
}
}
\ No newline at end of file
yd-oss-service/src/main/java/com/yd/oss/service/config/OssConfig.java
View file @
c5866e47
...
...
@@ -4,6 +4,7 @@ import com.aliyun.oss.OSS;
import
com.aliyun.oss.OSSClientBuilder
;
import
com.yd.oss.service.model.OssProvider
;
import
com.yd.oss.service.service.IOssProviderService
;
import
com.yd.oss.service.service.OssService
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.context.annotation.Bean
;
...
...
@@ -48,6 +49,12 @@ public class OssConfig {
);
}
// @Bean
// public OSS ossClient(OssService ossService) {
// // 返回动态代理,每次调用都委托给 ossService.getOssClient()
// return DynamicOssClientProxy.createProxy(ossService);
// }
@Bean
public
String
defaultBucket
()
{
return
defaultBucket
;
...
...
yd-oss-service/src/main/java/com/yd/oss/service/dto/OssUploadFileReqDto.java
View file @
c5866e47
...
...
@@ -15,6 +15,11 @@ import lombok.NoArgsConstructor;
public
class
OssUploadFileReqDto
{
/**
* 项目ID
*/
private
String
projectBizId
;
/**
* 对象类型
*/
private
String
objectType
;
...
...
yd-oss-service/src/main/java/com/yd/oss/service/model/OssFile.java
View file @
c5866e47
...
...
@@ -28,6 +28,18 @@ public class OssFile implements Serializable {
private
Long
id
;
/**
* 所属租户ID(业务id)
*/
@TableField
(
"tenant_biz_id"
)
private
String
tenantBizId
;
/**
* 所属项目ID(业务id)
*/
@TableField
(
"project_biz_id"
)
private
String
projectBizId
;
/**
* 对象类型
*/
@TableField
(
"object_type"
)
...
...
yd-oss-service/src/main/java/com/yd/oss/service/model/OssProvider.java
View file @
c5866e47
...
...
@@ -34,6 +34,18 @@ public class OssProvider implements Serializable {
private
String
providerBizId
;
/**
* 所属租户ID(业务id)
*/
@TableField
(
"tenant_biz_id"
)
private
String
tenantBizId
;
/**
* 所属项目ID(业务id)
*/
@TableField
(
"project_biz_id"
)
private
String
projectBizId
;
/**
* 服务商编码(业务编码)
*/
@TableField
(
"code"
)
...
...
yd-oss-service/src/main/java/com/yd/oss/service/service/AppointmentExcelService.java
View file @
c5866e47
...
...
@@ -6,5 +6,6 @@ public interface AppointmentExcelService {
String
exportAppointment
(
Map
<
String
,
Object
>
data
,
String
templateType
,
String
appointmentBizId
);
String
appointmentBizId
,
String
projectBizId
);
}
yd-oss-service/src/main/java/com/yd/oss/service/service/IOssProviderService.java
View file @
c5866e47
...
...
@@ -21,9 +21,13 @@ public interface IOssProviderService extends IService<OssProvider> {
OssProvider
getProviderById
(
Long
id
);
OssProvider
getProviderByBizId
(
String
providerBizId
);
List
<
OssProvider
>
getActiveProviders
();
boolean
saveProvider
(
OssProvider
provider
);
boolean
deleteProvider
(
Long
id
);
OssProvider
getProviderByProjectId
(
String
projectBizId
);
}
yd-oss-service/src/main/java/com/yd/oss/service/service/OssService.java
View file @
c5866e47
package
com
.
yd
.
oss
.
service
.
service
;
import
com.
yd.oss.feign.request.ApiUploadFileRequest
;
import
com.
aliyun.oss.OSS
;
import
com.yd.oss.service.dto.FileMetadata
;
import
com.yd.oss.service.dto.OssUploadFileReqDto
;
import
com.yd.oss.service.dto.OssUploadFileResDto
;
...
...
@@ -16,7 +16,7 @@ import java.time.Duration;
public
interface
OssService
{
// 上传文件
OssUploadFileResDto
uploadFile
(
InputStream
inputStream
,
String
fileName
,
String
bucketName
,
String
uploadUser
,
String
type
);
OssUploadFileResDto
uploadFile
(
InputStream
inputStream
,
String
fileName
,
String
bucketName
,
String
uploadUser
,
String
type
,
String
projectBizId
);
OssUploadFileResDto
uploadFileBody
(
MultipartFile
file
,
OssUploadFileReqDto
reqDto
);
...
...
@@ -32,6 +32,8 @@ public interface OssService {
// 删除文件
boolean
deleteFile
(
String
fileKey
,
String
bucketName
,
String
operator
);
boolean
deleteFileByBizId
(
String
fileBizId
,
String
operator
);
// 删除文件(使用默认存储桶)
boolean
deleteFile
(
String
fileKey
,
String
operator
);
...
...
@@ -53,12 +55,17 @@ public interface OssService {
// 获取文件元数据(使用默认存储桶)
FileMetadata
getFileMetadata
(
String
fileKey
);
void
switchProviderByProjectId
(
String
projectBizId
);
// 切换OSS提供商
void
switchProvider
(
String
providerName
);
// 切换OSS提供商(通过ID)
void
switchProvider
(
Long
providerId
);
//获取当前使用的 OSS 客户端
OSS
getOssClient
();
// 获取当前使用的提供商
OssProvider
getCurrentProvider
();
...
...
yd-oss-service/src/main/java/com/yd/oss/service/service/impl/AliYunOssServiceImpl.java
View file @
c5866e47
package
com
.
yd
.
oss
.
service
.
service
.
impl
;
import
com.aliyun.oss.OSS
;
import
com.aliyun.oss.OSSClientBuilder
;
import
com.aliyun.oss.model.CannedAccessControlList
;
import
com.aliyun.oss.model.OSSObject
;
import
com.aliyun.oss.model.ObjectMetadata
;
...
...
@@ -13,6 +12,7 @@ import com.yd.common.exception.BusinessException;
import
com.yd.common.utils.IpUtil
;
import
com.yd.common.utils.RandomStringGenerator
;
import
com.yd.oss.feign.request.ApiUploadFileRequest
;
import
com.yd.oss.service.config.OssClientFactory
;
import
com.yd.oss.service.dto.FileMetadata
;
import
com.yd.oss.service.dto.OssUploadFileReqDto
;
import
com.yd.oss.service.dto.OssUploadFileResDto
;
...
...
@@ -24,6 +24,7 @@ import com.yd.oss.service.service.IOssFileService;
import
com.yd.oss.service.service.IOssProviderService
;
import
com.yd.oss.service.service.OssService
;
import
com.yd.oss.service.utils.FileUtil
;
import
com.yd.oss.service.utils.OssUtils
;
import
lombok.extern.slf4j.Slf4j
;
import
org.apache.commons.lang3.StringUtils
;
import
org.springframework.beans.factory.annotation.Autowired
;
...
...
@@ -49,16 +50,15 @@ public class AliYunOssServiceImpl implements OssService {
private
IOssFileService
ossFileService
;
@Autowired
private
O
SS
ossClient
;
// 注入OSS客户端
private
O
ssClientFactory
ossClientFactory
;
@Autowired
private
String
defaultBucket
;
// 注入默认存储桶
private
OssUtils
ossUtils
;
@Autowired
private
String
defaultEndpoint
;
// 注入默认服务端点
@Autowired
private
OssProvider
currentProvider
;
// 注入当前提供商
// 默认提供商(用于没有传入项目ID或提供商ID的情况)
private
OssProvider
getDefaultProvider
()
{
return
ossProviderService
.
getDefaultProvider
();
}
/**
* 上传文件
...
...
@@ -67,106 +67,25 @@ public class AliYunOssServiceImpl implements OssService {
* @param bucketName OSS桶名
* @param uploadUser 操作用户
* @param type oss文件夹分类目录类型,例:如果是.xls那就是excel/
* @param projectBizId 项目业务ID(用于确定OSS提供商)
* @return
*/
@Override
public
OssUploadFileResDto
uploadFile
(
InputStream
inputStream
,
String
fileName
,
String
bucketName
,
String
uploadUser
,
String
type
)
{
//获取Security上下文当前用户的登录信息
AuthUserDto
authUserDto
=
SecurityUtil
.
getCurrentLoginUser
();
OssUploadFileResDto
ossUploadFileDto
=
new
OssUploadFileResDto
();
long
startTime
=
System
.
currentTimeMillis
();
// 记录开始时间
String
operationResult
=
"success"
;
// 操作结果
String
errorMessage
=
null
;
// 错误信息
OssFile
ossFile
=
null
;
// 文件记录
String
bucketName
,
String
uploadUser
,
String
type
,
String
projectBizId
)
{
// 获取提供商
OssProvider
provider
=
ossProviderService
.
getProviderByProjectId
(
projectBizId
);
if
(
provider
==
null
)
{
throw
new
BusinessException
(
"未找到项目对应的OSS提供商,projectBizId="
+
projectBizId
);
}
OSS
ossClient
=
null
;
try
{
// 读取输入流到字节数组
byte
[]
fileData
=
FileUtil
.
readInputStreamToBytes
(
inputStream
);
long
fileSize
=
fileData
.
length
;
ByteArrayInputStream
byteArrayInputStream
=
new
ByteArrayInputStream
(
fileData
);
// 生成文件key
String
fileKey
=
FileUtil
.
generateFileKey
(
fileName
,
type
);
String
actualBucket
=
StringUtils
.
isNotBlank
(
bucketName
)
?
bucketName
:
defaultBucket
;
String
fileType
=
FileUtil
.
getFileType
(
fileName
);
// 创建上传请求
ObjectMetadata
metadata
=
new
ObjectMetadata
();
metadata
.
setContentLength
(
fileSize
);
metadata
.
setContentType
(
FileUtil
.
getContentType
(
fileType
));
// 设置公共读权限(如果需要)
// metadata.setObjectAcl(CannedAccessControlList.PublicRead);
PutObjectRequest
putObjectRequest
=
new
PutObjectRequest
(
actualBucket
,
fileKey
,
byteArrayInputStream
,
metadata
);
// 上传文件
ossClient
.
putObject
(
putObjectRequest
);
// 创建文件记录
ossFile
=
new
OssFile
();
ossFile
.
setFileBizId
(
RandomStringGenerator
.
generateBizId16
(
CommonEnum
.
UID_TYPE_OSS_FILE
.
getCode
()));
ossFile
.
setFileKey
(
fileKey
);
ossFile
.
setOriginalName
(
fileName
);
ossFile
.
setFileSize
(
fileSize
);
ossFile
.
setFileType
(
fileType
);
ossFile
.
setProviderBizId
(
currentProvider
.
getProviderBizId
());
ossFile
.
setBucketName
(
actualBucket
);
ossFile
.
setUploadUser
(
uploadUser
);
ossFile
.
setCreatorId
(
authUserDto
.
getUserBizId
());
ossFile
.
setCreatorName
(
authUserDto
.
getUsername
());
// 保存文件元数据到数据库
ossFileService
.
saveFileMetadata
(
ossFile
);
// 创建操作日志
OssOperationLog
operationLog
=
new
OssOperationLog
();
operationLog
.
setFileBizId
(
ossFile
.
getFileBizId
());
operationLog
.
setOperationType
(
"upload"
);
operationLog
.
setOperationUser
(
uploadUser
);
operationLog
.
setOperationResult
(
operationResult
);
operationLog
.
setErrorMessage
(
errorMessage
);
operationLog
.
setClientIp
(
IpUtil
.
getClientIp
());
operationLog
.
setCostTime
(
System
.
currentTimeMillis
()
-
startTime
);
// 保存操作日志到数据库
ossFileService
.
saveOperationLog
(
operationLog
);
log
.
info
(
"文件上传成功: {} -> {}/{}"
,
fileName
,
actualBucket
,
fileKey
);
ossUploadFileDto
.
setFileBizId
(
ossFile
.
getFileBizId
());
ossUploadFileDto
.
setFileKey
(
fileKey
);
ossUploadFileDto
.
setOriginalName
(
fileName
);
// 如果设置了公共读,可以直接拼接URL
String
publicUrl
=
"https://"
+
actualBucket
+
"."
+
defaultEndpoint
+
"/"
+
fileKey
;
ossUploadFileDto
.
setUrl
(
publicUrl
);
return
ossUploadFileDto
;
}
catch
(
Exception
e
)
{
operationResult
=
"failure"
;
// 标记操作失败
errorMessage
=
e
.
getMessage
();
// 记录错误信息
log
.
error
(
"阿里云OSS上传文件失败: {}"
,
fileName
,
e
);
throw
new
RuntimeException
(
"阿里云OSS上传文件失败: "
+
fileName
,
e
);
ossClient
=
ossClientFactory
.
createOssClient
(
provider
);
return
doUploadFile
(
ossClient
,
provider
,
inputStream
,
fileName
,
bucketName
,
uploadUser
,
type
,
null
,
null
,
null
,
null
,
null
,
null
);
}
finally
{
// 关闭资源
FileUtil
.
closeQuietly
(
inputStream
);
// 记录失败日志
if
(
"failure"
.
equals
(
operationResult
))
{
OssOperationLog
operationLog
=
new
OssOperationLog
();
if
(
ossFile
!=
null
)
{
operationLog
.
setFileBizId
(
ossFile
.
getFileBizId
());
}
else
{
operationLog
.
setFileBizId
(
"-1"
);
// 使用无效文件ID
}
operationLog
.
setOperationType
(
"upload"
);
operationLog
.
setOperationUser
(
uploadUser
);
operationLog
.
setOperationResult
(
operationResult
);
operationLog
.
setErrorMessage
(
errorMessage
);
operationLog
.
setClientIp
(
IpUtil
.
getClientIp
());
operationLog
.
setCostTime
(
System
.
currentTimeMillis
()
-
startTime
);
// 保存操作日志到数据库
ossFileService
.
saveOperationLog
(
operationLog
);
if
(
ossClient
!=
null
)
{
ossClient
.
shutdown
();
}
}
}
...
...
@@ -179,51 +98,88 @@ public class AliYunOssServiceImpl implements OssService {
*/
@Override
public
OssUploadFileResDto
uploadFileBody
(
MultipartFile
file
,
OssUploadFileReqDto
reqDto
)
{
//获取Security上下文当前用户的登录信息
AuthUserDto
authUserDto
=
SecurityUtil
.
getCurrentLoginUser
();
OssUploadFileResDto
ossUploadFileDto
=
new
OssUploadFileResDto
();
// 记录开始时间
long
startTime
=
System
.
currentTimeMillis
();
// 操作结果
String
operationResult
=
"success"
;
// 错误信息
String
errorMessage
=
null
;
// 文件记录
OssFile
ossFile
=
null
;
//文件输入流
InputStream
inputStream
=
null
;
//原始文件名
String
fileName
=
file
.
getOriginalFilename
();
//文件扩展名
String
type
=
FileUtil
.
getFileType
(
file
.
getOriginalFilename
());
// 获取提供商
OssProvider
provider
=
ossProviderService
.
getProviderByProjectId
(
reqDto
.
getProjectBizId
());
if
(
provider
==
null
)
{
throw
new
BusinessException
(
"未找到项目对应的OSS提供商,projectBizId="
+
reqDto
.
getProjectBizId
());
}
OSS
ossClient
=
null
;
InputStream
inputStream
=
null
;
try
{
inputStream
=
file
.
getInputStream
();
ossClient
=
ossClientFactory
.
createOssClient
(
provider
);
return
doUploadFile
(
ossClient
,
provider
,
inputStream
,
file
.
getOriginalFilename
(),
provider
.
getBucketName
(),
reqDto
.
getUploadUser
(),
FileUtil
.
getFileType
(
file
.
getOriginalFilename
()),
reqDto
.
getObjectBizId
(),
reqDto
.
getObjectName
(),
reqDto
.
getObjectTableName
(),
reqDto
.
getObjectType
(),
reqDto
.
getObjectBizId
(),
reqDto
.
getObjectName
());
// 这里需要根据实际情况调整,原代码中存储了object信息
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
throw
new
BusinessException
(
"文件输入流解析异常:{}"
);
log
.
error
(
"文件输入流解析异常"
,
e
);
throw
new
BusinessException
(
"文件输入流解析异常"
);
}
finally
{
FileUtil
.
closeQuietly
(
inputStream
);
if
(
ossClient
!=
null
)
{
ossClient
.
shutdown
();
}
}
}
/**
* 上传文件(使用默认存储桶)
* @param inputStream
* @param fileName
* @param uploadUser
* @return
*/
@Override
public
String
uploadFile
(
InputStream
inputStream
,
String
fileName
,
String
uploadUser
)
{
// 使用默认提供商
OssProvider
defaultProvider
=
getDefaultProvider
();
OSS
ossClient
=
null
;
try
{
ossClient
=
ossClientFactory
.
createOssClient
(
defaultProvider
);
OssUploadFileResDto
result
=
doUploadFile
(
ossClient
,
defaultProvider
,
inputStream
,
fileName
,
defaultProvider
.
getBucketName
(),
uploadUser
,
null
,
null
,
null
,
null
,
null
,
null
,
null
);
return
result
.
getUrl
();
}
finally
{
if
(
ossClient
!=
null
)
{
ossClient
.
shutdown
();
}
}
}
/**
* 实际执行上传的逻辑(复用代码)
*/
private
OssUploadFileResDto
doUploadFile
(
OSS
ossClient
,
OssProvider
provider
,
InputStream
inputStream
,
String
fileName
,
String
bucketName
,
String
uploadUser
,
String
type
,
String
objectBizId
,
String
objectName
,
String
objectTableName
,
String
objectType
,
String
creatorId
,
String
creatorName
)
{
long
startTime
=
System
.
currentTimeMillis
();
String
operationResult
=
"success"
;
String
errorMessage
=
null
;
OssFile
ossFile
=
null
;
OssUploadFileResDto
ossUploadFileDto
=
new
OssUploadFileResDto
();
try
{
// 读取输入流到字节数组
byte
[]
fileData
=
FileUtil
.
readInputStreamToBytes
(
inputStream
);
long
fileSize
=
fileData
.
length
;
ByteArrayInputStream
byteArrayInputStream
=
new
ByteArrayInputStream
(
fileData
);
// 生成文件key
String
fileKey
=
FileUtil
.
generateFileKey
(
fileName
,
type
);
//默认阿里云的桶名
String
actualBucket
=
defaultBucket
;
//获取文件扩展名
// 生成文件key(这里使用ossUtils的方法,需要传入projectBizId,但此时provider已知,可根据需要调整)
String
fileKey
=
ossUtils
.
getFilePrefix
(
provider
.
getProviderBizId
(),
""
,
fileName
,
type
);
String
actualBucket
=
StringUtils
.
isNotBlank
(
bucketName
)
?
bucketName
:
provider
.
getBucketName
();
String
fileType
=
FileUtil
.
getFileType
(
fileName
);
// 创建上传请求
ObjectMetadata
metadata
=
new
ObjectMetadata
();
metadata
.
setContentLength
(
fileSize
);
metadata
.
setContentType
(
FileUtil
.
getContentType
(
fileType
));
// 设置公共读权限(如果需要)
// metadata.setObjectAcl(CannedAccessControlList.PublicRead);
PutObjectRequest
putObjectRequest
=
new
PutObjectRequest
(
actualBucket
,
fileKey
,
byteArrayInputStream
,
metadata
);
...
...
@@ -238,90 +194,67 @@ public class AliYunOssServiceImpl implements OssService {
ossFile
.
setOriginalName
(
fileName
);
ossFile
.
setFileSize
(
fileSize
);
ossFile
.
setFileType
(
fileType
);
ossFile
.
setProviderBizId
(
currentP
rovider
.
getProviderBizId
());
ossFile
.
setProviderBizId
(
p
rovider
.
getProviderBizId
());
ossFile
.
setBucketName
(
actualBucket
);
ossFile
.
setUploadUser
(
reqDto
.
getUploadUser
());
//存储对象信息
ossFile
.
setObjectBizId
(
reqDto
.
getObjectBizId
());
ossFile
.
setObjectName
(
reqDto
.
getObjectName
());
ossFile
.
setObjectTableName
(
reqDto
.
getObjectTableName
());
ossFile
.
setObjectType
(
reqDto
.
getObjectType
());
ossFile
.
setUploadUser
(
uploadUser
);
ossFile
.
setObjectBizId
(
objectBizId
);
ossFile
.
setObjectName
(
objectName
);
ossFile
.
setObjectTableName
(
objectTableName
);
ossFile
.
setObjectType
(
objectType
);
// 获取当前登录用户信息(如果存在)
AuthUserDto
authUserDto
=
SecurityUtil
.
getCurrentLoginUser
();
if
(
authUserDto
!=
null
)
{
ossFile
.
setCreatorId
(
authUserDto
.
getUserBizId
());
ossFile
.
setCreatorName
(
authUserDto
.
getUsername
());
// 保存文件元数据到数据库
}
else
{
ossFile
.
setCreatorId
(
creatorId
);
ossFile
.
setCreatorName
(
creatorName
);
}
ossFileService
.
saveFileMetadata
(
ossFile
);
//
创建
操作日志
//
记录成功
操作日志
OssOperationLog
operationLog
=
new
OssOperationLog
();
operationLog
.
setFileBizId
(
ossFile
.
getFileBizId
());
operationLog
.
setOperationType
(
"upload"
);
operationLog
.
setOperationUser
(
reqDto
.
getUploadUser
()
);
operationLog
.
setOperationUser
(
uploadUser
);
operationLog
.
setOperationResult
(
operationResult
);
operationLog
.
setErrorMessage
(
errorMessage
);
operationLog
.
setClientIp
(
IpUtil
.
getClientIp
());
operationLog
.
setCostTime
(
System
.
currentTimeMillis
()
-
startTime
);
// 保存操作日志到数据库
ossFileService
.
saveOperationLog
(
operationLog
);
log
.
info
(
"文件上传成功: {} -> {}/{}"
,
fileName
,
actualBucket
,
fileKey
);
ossUploadFileDto
.
setFileBizId
(
ossFile
.
getFileBizId
());
ossUploadFileDto
.
setFileKey
(
fileKey
);
ossUploadFileDto
.
setOriginalName
(
fileName
);
//
如果设置了公共读,可以直接拼接URL
String
publicUrl
=
"https://"
+
actualBucket
+
"."
+
defaultEndpoint
+
"/"
+
fileKey
;
//
构建访问URL(根据实际需要,可以是公共读或预签名URL)
String
publicUrl
=
"https://"
+
actualBucket
+
"."
+
provider
.
getEndpoint
()
+
"/"
+
fileKey
;
ossUploadFileDto
.
setUrl
(
publicUrl
);
ossUploadFileDto
.
setFileSize
(
fileSize
);
ossUploadFileDto
.
setFileType
(
fileType
);
return
ossUploadFileDto
;
}
catch
(
Exception
e
)
{
// 标记操作失败
operationResult
=
"failure"
;
// 记录错误信息
errorMessage
=
e
.
getMessage
();
log
.
error
(
"
阿里云
OSS上传文件失败: {}"
,
fileName
,
e
);
throw
new
RuntimeException
(
"
阿里云
OSS上传文件失败: "
+
fileName
,
e
);
log
.
error
(
"OSS上传文件失败: {}"
,
fileName
,
e
);
throw
new
RuntimeException
(
"OSS上传文件失败: "
+
fileName
,
e
);
}
finally
{
// 关闭资源
FileUtil
.
closeQuietly
(
inputStream
);
// 记录失败日志
// 记录失败日志(如果失败)
if
(
"failure"
.
equals
(
operationResult
))
{
OssOperationLog
operationLog
=
new
OssOperationLog
();
if
(
ossFile
!=
null
)
{
operationLog
.
setFileBizId
(
ossFile
.
getFileBizId
());
}
else
{
// 使用无效文件ID
operationLog
.
setFileBizId
(
"-1"
);
}
operationLog
.
setFileBizId
(
ossFile
!=
null
?
ossFile
.
getFileBizId
()
:
"-1"
);
operationLog
.
setOperationType
(
"upload"
);
operationLog
.
setOperationUser
(
reqDto
.
getUploadUser
()
);
operationLog
.
setOperationUser
(
uploadUser
);
operationLog
.
setOperationResult
(
operationResult
);
operationLog
.
setErrorMessage
(
errorMessage
);
operationLog
.
setClientIp
(
IpUtil
.
getClientIp
());
operationLog
.
setCostTime
(
System
.
currentTimeMillis
()
-
startTime
);
// 保存操作日志到数据库
ossFileService
.
saveOperationLog
(
operationLog
);
}
}
}
/**
* 上传文件(使用默认存储桶)
* @param inputStream
* @param fileName
* @param uploadUser
* @return
*/
@Override
public
String
uploadFile
(
InputStream
inputStream
,
String
fileName
,
String
uploadUser
)
{
// 调用重载方法,使用默认存储桶
// return uploadFile(inputStream, fileName, defaultBucket, uploadUser);
return
null
;
}
/**
* 下载文件
* @param fileKey
* @param bucketName
...
...
@@ -329,61 +262,46 @@ public class AliYunOssServiceImpl implements OssService {
*/
@Override
public
InputStream
downloadFile
(
String
fileKey
,
String
bucketName
)
{
long
startTime
=
System
.
currentTimeMillis
();
// 记录开始时间
String
operationResult
=
"success"
;
// 操作结果
String
errorMessage
=
null
;
// 错误信息
OssFile
ossFile
=
null
;
// 文件记录
// 根据文件key获取提供商信息
OssFile
ossFile
=
ossFileService
.
getFileByKey
(
fileKey
);
if
(
ossFile
==
null
)
{
throw
new
BusinessException
(
"文件不存在: "
+
fileKey
);
}
OssProvider
provider
=
ossProviderService
.
getProviderByBizId
(
ossFile
.
getProviderBizId
());
if
(
provider
==
null
)
{
throw
new
BusinessException
(
"提供商不存在: "
+
ossFile
.
getProviderBizId
());
}
OSS
ossClient
=
null
;
try
{
// 确定存储桶(如果未指定则使用默认存储桶)
String
actualBucket
=
StringUtils
.
isNotBlank
(
bucketName
)
?
bucketName
:
defaultBucket
;
ossClient
=
ossClientFactory
.
createOssClient
(
provider
);
String
actualBucket
=
StringUtils
.
isNotBlank
(
bucketName
)
?
bucketName
:
ossFile
.
getBucketName
()
;
// 获取文件信息
ossFile
=
ossFileService
.
getFileByKey
(
fileKey
);
// 从阿里云OSS下载文件
OSSObject
ossObject
=
ossClient
.
getObject
(
actualBucket
,
fileKey
);
InputStream
inputStream
=
ossObject
.
getObjectContent
();
// 创建操作日志
OssOperationLog
operationLog
=
new
OssOperationLog
();
operationLog
.
setFileBizId
(
ossFile
.
getFileBizId
());
operationLog
.
setOperationType
(
"download"
);
operationLog
.
setOperationUser
(
"system"
);
// 系统操作
operationLog
.
setOperationResult
(
operationResult
);
operationLog
.
setErrorMessage
(
errorMessage
);
operationLog
.
setClientIp
(
IpUtil
.
getClientIp
());
operationLog
.
setCostTime
(
System
.
currentTimeMillis
()
-
startTime
);
// 保存操作日志到数据库
ossFileService
.
saveOperationLog
(
operationLog
);
// 记录操作日志(成功)
recordOperationLog
(
ossFile
.
getFileBizId
(),
"download"
,
"system"
,
"success"
,
null
,
System
.
currentTimeMillis
());
log
.
info
(
"文件下载成功: {}/{}"
,
actualBucket
,
fileKey
);
// 注意:返回的InputStream需要由调用者负责关闭,但OSS客户端必须在此方法内关闭?
// 不能关闭,因为流还未消费完。此处需要特殊处理:返回的流内部可能关联OSSClient,调用者使用后需主动关闭。
// 一个解决方案是使用包装流,在close时同时关闭OSSClient。但为简化,这里不处理,要求调用者显式关闭。
// 更好的做法是返回一个包装流,但需要改造。为了示例,我们保留原逻辑,但强调调用者需要关闭流并手动shutdown客户端。
// 由于客户端不能在这里关闭,我们不得不将客户端保留到流消费完。这会导致资源泄漏。
// 因此,建议将下载操作设计为直接返回字节数组或使用回调,或者使用预签名URL让客户端直接下载。
// 这里为了演示,我们返回流,但客户端无法在这里关闭,存在风险。
// 实际使用时,可考虑返回预签名URL或使用临时文件。
// 此处暂时返回流,并记录警告。
log
.
warn
(
"返回原始InputStream,调用者必须确保在使用后关闭流,并注意OSSClient资源管理。"
);
return
inputStream
;
}
catch
(
Exception
e
)
{
operationResult
=
"failure"
;
// 标记操作失败
errorMessage
=
e
.
getMessage
();
// 记录错误信息
log
.
error
(
"阿里云OSS下载文件失败: {}"
,
fileKey
,
e
);
throw
new
RuntimeException
(
"阿里云OSS下载文件失败: "
+
fileKey
,
e
);
recordOperationLog
(
ossFile
!=
null
?
ossFile
.
getFileBizId
()
:
"-1"
,
"download"
,
"system"
,
"failure"
,
e
.
getMessage
(),
System
.
currentTimeMillis
());
log
.
error
(
"OSS下载文件失败: {}"
,
fileKey
,
e
);
throw
new
RuntimeException
(
"OSS下载文件失败: "
+
fileKey
,
e
);
}
finally
{
// 记录失败日志
if
(
"failure"
.
equals
(
operationResult
))
{
OssOperationLog
operationLog
=
new
OssOperationLog
();
if
(
ossFile
!=
null
)
{
operationLog
.
setFileBizId
(
ossFile
.
getFileBizId
());
}
else
{
operationLog
.
setFileBizId
(
"-1"
);
// 使用无效文件ID
}
operationLog
.
setOperationType
(
"download"
);
operationLog
.
setOperationUser
(
"system"
);
operationLog
.
setOperationResult
(
operationResult
);
operationLog
.
setErrorMessage
(
errorMessage
);
operationLog
.
setClientIp
(
IpUtil
.
getClientIp
());
operationLog
.
setCostTime
(
System
.
currentTimeMillis
()
-
startTime
);
// 保存操作日志到数据库
ossFileService
.
saveOperationLog
(
operationLog
);
}
// 注意:不能在这里shutdown,因为InputStream可能还未消费完。但如果不shutdown,客户端会一直保持连接。
// 这是一个设计问题。实际生产环境建议使用预签名URL或临时文件下载。
}
}
...
...
@@ -394,8 +312,7 @@ public class AliYunOssServiceImpl implements OssService {
*/
@Override
public
InputStream
downloadFile
(
String
fileKey
)
{
// 调用重载方法,使用默认存储桶
return
downloadFile
(
fileKey
,
defaultBucket
);
return
downloadFile
(
fileKey
,
null
);
}
/**
...
...
@@ -407,62 +324,66 @@ public class AliYunOssServiceImpl implements OssService {
*/
@Override
public
boolean
deleteFile
(
String
fileKey
,
String
bucketName
,
String
operator
)
{
long
startTime
=
System
.
currentTimeMillis
();
// 记录开始时间
String
operationResult
=
"success"
;
// 操作结果
String
errorMessage
=
null
;
// 错误信息
OssFile
ossFile
=
null
;
// 文件记录
OssFile
ossFile
=
ossFileService
.
getFileByKey
(
fileKey
);
if
(
ossFile
==
null
)
{
throw
new
BusinessException
(
"文件不存在: "
+
fileKey
);
}
OssProvider
provider
=
ossProviderService
.
getProviderByBizId
(
ossFile
.
getProviderBizId
());
if
(
provider
==
null
)
{
throw
new
BusinessException
(
"提供商不存在: "
+
ossFile
.
getProviderBizId
());
}
OSS
ossClient
=
null
;
long
startTime
=
System
.
currentTimeMillis
();
try
{
// 确定存储桶(如果未指定则使用默认存储桶)
String
actualBucket
=
StringUtils
.
isNotBlank
(
bucketName
)
?
bucketName
:
defaultBucket
;
ossClient
=
ossClientFactory
.
createOssClient
(
provider
);
String
actualBucket
=
StringUtils
.
isNotBlank
(
bucketName
)
?
bucketName
:
ossFile
.
getBucketName
()
;
// 获取文件信息
ossFile
=
ossFileService
.
getFileByKey
(
fileKey
);
// 从阿里云OSS删除文件 TODO
ossClient
.
deleteObject
(
actualBucket
,
ossFile
.
getFileKey
());
// 标记文件为已删除
ossFileService
.
markFileAsDeleted
(
fileKey
);
// 创建操作日志
OssOperationLog
operationLog
=
new
OssOperationLog
();
operationLog
.
setFileBizId
(
ossFile
.
getFileBizId
());
operationLog
.
setOperationType
(
"delete"
);
operationLog
.
setOperationUser
(
operator
);
operationLog
.
setOperationResult
(
operationResult
);
operationLog
.
setErrorMessage
(
errorMessage
);
operationLog
.
setClientIp
(
IpUtil
.
getClientIp
());
operationLog
.
setCostTime
(
System
.
currentTimeMillis
()
-
startTime
);
// 保存操作日志到数据库
ossFileService
.
saveOperationLog
(
operationLog
);
recordOperationLog
(
ossFile
.
getFileBizId
(),
"delete"
,
operator
,
"success"
,
null
,
startTime
);
log
.
info
(
"文件删除成功: {}/{}"
,
actualBucket
,
fileKey
);
return
true
;
}
catch
(
Exception
e
)
{
operationResult
=
"failure"
;
// 标记操作失败
errorMessage
=
e
.
getMessage
();
// 记录错误信息
log
.
error
(
"阿里云OSS删除文件失败: {}"
,
fileKey
,
e
);
throw
new
RuntimeException
(
"阿里云OSS删除文件失败: "
+
fileKey
,
e
);
recordOperationLog
(
ossFile
.
getFileBizId
(),
"delete"
,
operator
,
"failure"
,
e
.
getMessage
(),
startTime
);
log
.
error
(
"OSS删除文件失败: {}"
,
fileKey
,
e
);
throw
new
RuntimeException
(
"OSS删除文件失败: "
+
fileKey
,
e
);
}
finally
{
// 记录失败日志
if
(
"failure"
.
equals
(
operationResult
))
{
OssOperationLog
operationLog
=
new
OssOperationLog
();
if
(
ossFile
!=
null
)
{
operationLog
.
setFileBizId
(
ossFile
.
getFileBizId
());
}
else
{
operationLog
.
setFileBizId
(
"-1"
);
// 使用无效文件ID
if
(
ossClient
!=
null
)
{
ossClient
.
shutdown
();
}
}
}
operationLog
.
setOperationType
(
"delete"
);
operationLog
.
setOperationUser
(
operator
);
operationLog
.
setOperationResult
(
operationResult
);
operationLog
.
setErrorMessage
(
errorMessage
);
operationLog
.
setClientIp
(
IpUtil
.
getClientIp
());
operationLog
.
setCostTime
(
System
.
currentTimeMillis
()
-
startTime
);
// 保存操作日志到数据库
ossFileService
.
saveOperationLog
(
operationLog
);
@Override
public
boolean
deleteFileByBizId
(
String
fileBizId
,
String
operator
)
{
OssFile
ossFile
=
ossFileService
.
queryOne
(
fileBizId
);
if
(
ossFile
==
null
)
{
throw
new
BusinessException
(
"文件不存在: "
+
fileBizId
);
}
OssProvider
provider
=
ossProviderService
.
getProviderByBizId
(
ossFile
.
getProviderBizId
());
if
(
provider
==
null
)
{
throw
new
BusinessException
(
"提供商不存在: "
+
ossFile
.
getProviderBizId
());
}
OSS
ossClient
=
null
;
long
startTime
=
System
.
currentTimeMillis
();
try
{
ossClient
=
ossClientFactory
.
createOssClient
(
provider
);
ossClient
.
deleteObject
(
ossFile
.
getBucketName
(),
ossFile
.
getFileKey
());
ossFileService
.
removeById
(
ossFile
.
getId
());
recordOperationLog
(
ossFile
.
getFileBizId
(),
"delete"
,
operator
,
"success"
,
null
,
startTime
);
log
.
info
(
"文件删除成功: {}/{}"
,
ossFile
.
getBucketName
(),
ossFile
.
getFileKey
());
return
true
;
}
catch
(
Exception
e
)
{
recordOperationLog
(
ossFile
.
getFileBizId
(),
"delete"
,
operator
,
"failure"
,
e
.
getMessage
(),
startTime
);
log
.
error
(
"删除文件失败: fileBizId={}"
,
fileBizId
,
e
);
throw
new
RuntimeException
(
"删除文件失败: "
+
fileBizId
,
e
);
}
finally
{
if
(
ossClient
!=
null
)
{
ossClient
.
shutdown
();
}
}
}
...
...
@@ -475,12 +396,11 @@ public class AliYunOssServiceImpl implements OssService {
*/
@Override
public
boolean
deleteFile
(
String
fileKey
,
String
operator
)
{
// 调用重载方法,使用默认存储桶
return
deleteFile
(
fileKey
,
defaultBucket
,
operator
);
return
deleteFile
(
fileKey
,
null
,
operator
);
}
/**
* 获取文件URL
* 获取文件URL
(预签名)
* @param fileKey
* @param bucketName
* @param expiration
...
...
@@ -488,18 +408,29 @@ public class AliYunOssServiceImpl implements OssService {
*/
@Override
public
String
getFileUrl
(
String
fileKey
,
String
bucketName
,
Duration
expiration
)
{
try
{
// 确定存储桶(如果未指定则使用默认存储桶)
String
actualBucket
=
StringUtils
.
isNotBlank
(
bucketName
)
?
bucketName
:
defaultBucket
;
OssFile
ossFile
=
ossFileService
.
getFileByKey
(
fileKey
);
if
(
ossFile
==
null
)
{
throw
new
BusinessException
(
"文件不存在: "
+
fileKey
);
}
OssProvider
provider
=
ossProviderService
.
getProviderByBizId
(
ossFile
.
getProviderBizId
());
if
(
provider
==
null
)
{
throw
new
BusinessException
(
"提供商不存在: "
+
ossFile
.
getProviderBizId
());
}
// 生成预签名URL(带过期时间)
OSS
ossClient
=
null
;
try
{
ossClient
=
ossClientFactory
.
createOssClient
(
provider
);
String
actualBucket
=
StringUtils
.
isNotBlank
(
bucketName
)
?
bucketName
:
ossFile
.
getBucketName
();
Date
expirationDate
=
new
Date
(
System
.
currentTimeMillis
()
+
expiration
.
toMillis
());
URL
url
=
ossClient
.
generatePresignedUrl
(
actualBucket
,
fileKey
,
expirationDate
);
return
url
.
toString
();
}
catch
(
Exception
e
)
{
log
.
error
(
"阿里云OSS获取文件URL失败: {}"
,
fileKey
,
e
);
throw
new
RuntimeException
(
"阿里云OSS获取文件URL失败: "
+
fileKey
,
e
);
log
.
error
(
"获取文件URL失败: {}"
,
fileKey
,
e
);
throw
new
RuntimeException
(
"获取文件URL失败: "
+
fileKey
,
e
);
}
finally
{
if
(
ossClient
!=
null
)
{
ossClient
.
shutdown
();
}
}
}
...
...
@@ -511,8 +442,7 @@ public class AliYunOssServiceImpl implements OssService {
*/
@Override
public
String
getFileUrl
(
String
fileKey
,
Duration
expiration
)
{
// 调用重载方法,使用默认存储桶
return
getFileUrl
(
fileKey
,
defaultBucket
,
expiration
);
return
getFileUrl
(
fileKey
,
null
,
expiration
);
}
/**
...
...
@@ -523,15 +453,27 @@ public class AliYunOssServiceImpl implements OssService {
*/
@Override
public
boolean
doesFileExist
(
String
fileKey
,
String
bucketName
)
{
try
{
// 确定存储桶(如果未指定则使用默认存储桶)
String
actualBucket
=
StringUtils
.
isNotBlank
(
bucketName
)
?
bucketName
:
defaultBucket
;
OssFile
ossFile
=
ossFileService
.
getFileByKey
(
fileKey
);
if
(
ossFile
==
null
)
{
return
false
;
}
OssProvider
provider
=
ossProviderService
.
getProviderByBizId
(
ossFile
.
getProviderBizId
());
if
(
provider
==
null
)
{
return
false
;
}
// 检查文件是否存在
OSS
ossClient
=
null
;
try
{
ossClient
=
ossClientFactory
.
createOssClient
(
provider
);
String
actualBucket
=
StringUtils
.
isNotBlank
(
bucketName
)
?
bucketName
:
ossFile
.
getBucketName
();
return
ossClient
.
doesObjectExist
(
actualBucket
,
fileKey
);
}
catch
(
Exception
e
)
{
log
.
error
(
"阿里云OSS检查文件存在失败: {}"
,
fileKey
,
e
);
throw
new
RuntimeException
(
"阿里云OSS检查文件存在失败: "
+
fileKey
,
e
);
log
.
error
(
"检查文件存在失败: {}"
,
fileKey
,
e
);
return
false
;
}
finally
{
if
(
ossClient
!=
null
)
{
ossClient
.
shutdown
();
}
}
}
...
...
@@ -542,8 +484,7 @@ public class AliYunOssServiceImpl implements OssService {
*/
@Override
public
boolean
doesFileExist
(
String
fileKey
)
{
// 调用重载方法,使用默认存储桶
return
doesFileExist
(
fileKey
,
defaultBucket
);
return
doesFileExist
(
fileKey
,
null
);
}
/**
...
...
@@ -554,25 +495,36 @@ public class AliYunOssServiceImpl implements OssService {
*/
@Override
public
FileMetadata
getFileMetadata
(
String
fileKey
,
String
bucketName
)
{
try
{
// 确定存储桶(如果未指定则使用默认存储桶)
String
actualBucket
=
StringUtils
.
isNotBlank
(
bucketName
)
?
bucketName
:
defaultBucket
;
OssFile
ossFile
=
ossFileService
.
getFileByKey
(
fileKey
);
if
(
ossFile
==
null
)
{
throw
new
BusinessException
(
"文件不存在: "
+
fileKey
);
}
OssProvider
provider
=
ossProviderService
.
getProviderByBizId
(
ossFile
.
getProviderBizId
());
if
(
provider
==
null
)
{
throw
new
BusinessException
(
"提供商不存在: "
+
ossFile
.
getProviderBizId
());
}
// 获取文件元数据
OSS
ossClient
=
null
;
try
{
ossClient
=
ossClientFactory
.
createOssClient
(
provider
);
String
actualBucket
=
StringUtils
.
isNotBlank
(
bucketName
)
?
bucketName
:
ossFile
.
getBucketName
();
ObjectMetadata
objectMetadata
=
ossClient
.
getObjectMetadata
(
actualBucket
,
fileKey
);
// 转换为通用文件元数据格式
FileMetadata
metadata
=
new
FileMetadata
();
metadata
.
setFileKey
(
fileKey
);
metadata
.
setFileSize
(
objectMetadata
.
getContentLength
());
metadata
.
setContentType
(
objectMetadata
.
getContentType
());
// metadata.setLastModified(objectMetadata.getLastModified());
metadata
.
setEtag
(
objectMetadata
.
getETag
());
// 如果有最后修改时间,可设置
// metadata.setLastModified(objectMetadata.getLastModified());
return
metadata
;
}
catch
(
Exception
e
)
{
log
.
error
(
"阿里云OSS获取文件元数据失败: {}"
,
fileKey
,
e
);
throw
new
RuntimeException
(
"阿里云OSS获取文件元数据失败: "
+
fileKey
,
e
);
log
.
error
(
"获取文件元数据失败: {}"
,
fileKey
,
e
);
throw
new
RuntimeException
(
"获取文件元数据失败: "
+
fileKey
,
e
);
}
finally
{
if
(
ossClient
!=
null
)
{
ossClient
.
shutdown
();
}
}
}
...
...
@@ -583,118 +535,77 @@ public class AliYunOssServiceImpl implements OssService {
*/
@Override
public
FileMetadata
getFileMetadata
(
String
fileKey
)
{
// 调用重载方法,使用默认存储桶
return
getFileMetadata
(
fileKey
,
defaultBucket
);
return
getFileMetadata
(
fileKey
,
null
);
}
/**
* 切换OSS提供商
* @param providerName
* 切换OSS提供商-根据项目ID切换(已废弃,由每次操作动态决定,保留空实现)
*/
@Override
public
void
switchProvider
(
String
providerName
)
{
try
{
// 根据名称获取OSS提供商
OssProvider
provider
=
ossProviderService
.
getProviderByName
(
providerName
);
// 切换到新的提供商
switchToProvider
(
provider
);
log
.
info
(
"已切换到OSS提供商: {}"
,
providerName
);
}
catch
(
Exception
e
)
{
log
.
error
(
"切换OSS提供商失败: {}"
,
providerName
,
e
);
throw
new
RuntimeException
(
"切换OSS提供商失败: "
+
providerName
,
e
);
}
public
void
switchProviderByProjectId
(
String
projectBizId
)
{
// 不再需要
}
/**
* 切换OSS提供商(通过ID)
* @param providerId
* 切换OSS提供商(已废弃)
*/
@Override
public
void
switchProvider
(
Long
providerId
)
{
try
{
// 根据ID获取OSS提供商
OssProvider
provider
=
ossProviderService
.
getProviderById
(
providerId
);
// 切换到新的提供商
switchToProvider
(
provider
);
log
.
info
(
"已切换到OSS提供商ID: {}"
,
providerId
);
}
catch
(
Exception
e
)
{
log
.
error
(
"切换OSS提供商失败: {}"
,
providerId
,
e
);
throw
new
RuntimeException
(
"切换OSS提供商失败: "
+
providerId
,
e
);
}
public
void
switchProvider
(
String
providerName
)
{
// 不再需要
}
/**
* 切换到指定的OSS提供商
* @param provider
* 切换OSS提供商(已废弃)
*/
private
void
switchToProvider
(
OssProvider
provider
)
{
// 关闭旧的客户端
if
(
this
.
ossClient
!=
null
)
{
this
.
ossClient
.
shutdown
();
@Override
public
void
switchProvider
(
Long
providerId
)
{
// 不再需要
}
// 创建新的客户端
this
.
currentProvider
=
provider
;
this
.
ossClient
=
new
OSSClientBuilder
().
build
(
provider
.
getEndpoint
(),
provider
.
getAccessKey
(),
provider
.
getSecretKey
()
);
this
.
defaultBucket
=
provider
.
getBucketName
();
/**
* 获取当前使用的 OSS 客户端(已废弃,返回null)
*/
@Override
public
OSS
getOssClient
()
{
return
null
;
}
/**
* 获取当前使用的提供商
* @return
* 获取当前使用的提供商(已废弃,返回默认提供商)
*/
@Override
public
OssProvider
getCurrentProvider
()
{
return
currentProvider
;
return
getDefaultProvider
()
;
}
/**
* 设置默认存储桶
* @param bucketName
* 设置默认存储桶(已废弃)
*/
@Override
public
void
setDefaultBucket
(
String
bucketName
)
{
this
.
defaultBucket
=
bucketName
;
log
.
info
(
"已设置默认存储桶: {}"
,
bucketName
);
// 不再需要
}
/**
* 获取默认存储桶
* @return
* 获取默认存储桶(已废弃,返回默认提供商的桶)
*/
@Override
public
String
getDefaultBucket
()
{
return
defaultBucket
;
return
getDefaultProvider
().
getBucketName
()
;
}
/**
* 获取上传结果(包含文件信息和访问URL)
* @param fileKey
* @param expiration
* @return
* 获取上传结果
*/
@Override
public
UploadResult
getUploadResult
(
String
fileKey
,
Duration
expiration
)
{
try
{
// 获取文件信息
OssFile
file
=
ossFileService
.
getFileByKey
(
fileKey
);
// 生成访问URL
if
(
file
==
null
)
{
throw
new
BusinessException
(
"文件不存在: "
+
fileKey
);
}
String
accessUrl
=
getFileUrl
(
fileKey
,
expiration
);
String
url
=
accessUrl
.
split
(
"\\?"
)[
0
];
// 使用 split 方法以 "?" 为分隔符分割字符串
String
[]
parts
=
accessUrl
.
split
(
"\\?"
);
String
url
=
parts
[
0
];
// 取问号之前的部分
// 创建上传结果
UploadResult
result
=
new
UploadResult
();
result
.
setFileKey
(
fileKey
);
result
.
setAccessUrl
(
accessUrl
);
...
...
@@ -703,100 +614,57 @@ public class AliYunOssServiceImpl implements OssService {
result
.
setFileType
(
file
.
getFileType
());
result
.
setOriginalName
(
file
.
getOriginalName
());
result
.
setUploadTime
(
file
.
getUploadTime
());
return
result
;
}
catch
(
Exception
e
)
{
log
.
error
(
"获取上传结果失败: {}"
,
fileKey
,
e
);
throw
new
RuntimeException
(
"获取上传结果失败: "
+
fileKey
,
e
);
}
}
/**
* 创建虚拟文件记录(用于操作日志)
* @return
*/
private
OssFile
createDummyOssFile
()
{
OssFile
file
=
new
OssFile
();
file
.
setId
(-
1L
);
// 使用无效ID
return
file
;
}
/**
* 上传字节数组到OSS并设置为公共读权限
* @param content 文件内容字节数组
* @param fileName 文件名
* @return 公共访问URL
* 上传字节数组并设置公共读(示例方法)
*/
public
String
upload
(
byte
[]
content
,
String
fileName
)
{
OssProvider
defaultProvider
=
getDefaultProvider
();
OSS
ossClient
=
null
;
try
{
// 生成唯一文件名
ossClient
=
ossClientFactory
.
createOssClient
(
defaultProvider
);
String
objectName
=
"appointment/excel/"
+
UUID
.
randomUUID
()
+
"/"
+
fileName
;
// 创建上传请求
PutObjectRequest
putObjectRequest
=
new
PutObjectRequest
(
defaultBucket
,
objectName
,
new
ByteArrayInputStream
(
content
)
);
// 上传文件
defaultProvider
.
getBucketName
(),
objectName
,
new
ByteArrayInputStream
(
content
));
ossClient
.
putObject
(
putObjectRequest
);
// 设置对象访问权限为公共读
ossClient
.
setObjectAcl
(
defaultBucket
,
objectName
,
CannedAccessControlList
.
PublicRead
);
// 构造公共访问URL
String
publicUrl
=
"https://"
+
defaultBucket
+
"."
+
defaultEndpoint
+
"/"
+
objectName
;
return
publicUrl
;
}
catch
(
Exception
e
)
{
throw
new
RuntimeException
(
"上传文件到OSS失败"
,
e
);
ossClient
.
setObjectAcl
(
defaultProvider
.
getBucketName
(),
objectName
,
CannedAccessControlList
.
PublicRead
);
return
"https://"
+
defaultProvider
.
getBucketName
()
+
"."
+
defaultProvider
.
getEndpoint
()
+
"/"
+
objectName
;
}
finally
{
if
(
ossClient
!=
null
)
{
ossClient
.
shutdown
();
}
}
}
/**
* 上传输入流到OSS并设置为公共读权限
* @param inputStream 文件输入流
* @param fileName 文件名
* @return 公共访问URL
* 上传输入流并设置公共读
*/
public
String
upload
(
InputStream
inputStream
,
String
fileName
)
{
OssProvider
defaultProvider
=
getDefaultProvider
();
OSS
ossClient
=
null
;
try
{
// 生成唯一文件名
ossClient
=
ossClientFactory
.
createOssClient
(
defaultProvider
);
String
objectName
=
"appointment/excel/"
+
UUID
.
randomUUID
()
+
"/"
+
fileName
;
// 创建上传请求
PutObjectRequest
putObjectRequest
=
new
PutObjectRequest
(
defaultBucket
,
objectName
,
inputStream
);
// 上传文件
defaultProvider
.
getBucketName
(),
objectName
,
inputStream
);
ossClient
.
putObject
(
putObjectRequest
);
// 设置对象访问权限为公共读
ossClient
.
setObjectAcl
(
defaultBucket
,
objectName
,
CannedAccessControlList
.
PublicRead
);
// 构造公共访问URL
String
publicUrl
=
"https://"
+
defaultBucket
+
"."
+
defaultEndpoint
+
"/"
+
objectName
;
return
publicUrl
;
}
catch
(
Exception
e
)
{
throw
new
RuntimeException
(
"上传文件到OSS失败"
,
e
);
ossClient
.
setObjectAcl
(
defaultProvider
.
getBucketName
(),
objectName
,
CannedAccessControlList
.
PublicRead
);
return
"https://"
+
defaultProvider
.
getBucketName
()
+
"."
+
defaultProvider
.
getEndpoint
()
+
"/"
+
objectName
;
}
finally
{
if
(
ossClient
!=
null
)
{
ossClient
.
shutdown
();
}
}
}
/**
* 批量上传文件
* @param files 文件列表
* @param reqDto 上传请求参数
* @return 批量上传响应
*/
@Override
public
com
.
yd
.
oss
.
feign
.
response
.
ApiBatchUploadResponse
batchUploadFiles
(
java
.
util
.
List
<
MultipartFile
>
files
,
OssUploadFileReqDto
reqDto
)
{
com
.
yd
.
oss
.
feign
.
response
.
ApiBatchUploadResponse
response
=
new
com
.
yd
.
oss
.
feign
.
response
.
ApiBatchUploadResponse
();
java
.
util
.
List
<
com
.
yd
.
oss
.
feign
.
response
.
ApiUploadResponse
>
successFiles
=
new
java
.
util
.
ArrayList
<>();
java
.
util
.
List
<
com
.
yd
.
oss
.
feign
.
response
.
ApiBatchUploadResponse
.
FailedFile
>
failedFiles
=
new
java
.
util
.
ArrayList
<>();
...
...
@@ -811,10 +679,7 @@ public class AliYunOssServiceImpl implements OssService {
for
(
MultipartFile
file
:
files
)
{
try
{
// 调用单文件上传方法
OssUploadFileResDto
uploadResult
=
uploadFileBody
(
file
,
reqDto
);
// 转换为ApiUploadResponse
com
.
yd
.
oss
.
feign
.
response
.
ApiUploadResponse
uploadResponse
=
new
com
.
yd
.
oss
.
feign
.
response
.
ApiUploadResponse
();
uploadResponse
.
setFileBizId
(
uploadResult
.
getFileBizId
());
uploadResponse
.
setFileKey
(
uploadResult
.
getFileKey
());
...
...
@@ -822,7 +687,6 @@ public class AliYunOssServiceImpl implements OssService {
uploadResponse
.
setUrl
(
uploadResult
.
getUrl
());
uploadResponse
.
setFileSize
(
uploadResult
.
getFileSize
());
uploadResponse
.
setFileType
(
uploadResult
.
getFileType
());
successFiles
.
add
(
uploadResponse
);
}
catch
(
Exception
e
)
{
log
.
error
(
"批量上传文件失败: {}"
,
file
.
getOriginalFilename
(),
e
);
...
...
@@ -838,9 +702,23 @@ public class AliYunOssServiceImpl implements OssService {
response
.
setFailedFiles
(
failedFiles
);
response
.
setSuccessCount
(
successFiles
.
size
());
response
.
setFailedCount
(
failedFiles
.
size
());
log
.
info
(
"批量上传完成: 成功{}个, 失败{}个"
,
successFiles
.
size
(),
failedFiles
.
size
());
return
response
;
}
/**
* 记录操作日志(公共方法)
*/
private
void
recordOperationLog
(
String
fileBizId
,
String
operationType
,
String
operator
,
String
result
,
String
errorMsg
,
long
startTime
)
{
OssOperationLog
operationLog
=
new
OssOperationLog
();
operationLog
.
setFileBizId
(
fileBizId
);
operationLog
.
setOperationType
(
operationType
);
operationLog
.
setOperationUser
(
operator
);
operationLog
.
setOperationResult
(
result
);
operationLog
.
setErrorMessage
(
errorMsg
);
operationLog
.
setClientIp
(
IpUtil
.
getClientIp
());
operationLog
.
setCostTime
(
System
.
currentTimeMillis
()
-
startTime
);
ossFileService
.
saveOperationLog
(
operationLog
);
}
}
\ No newline at end of file
yd-oss-service/src/main/java/com/yd/oss/service/service/impl/AppointmentExcelServiceImpl.java
View file @
c5866e47
...
...
@@ -40,7 +40,7 @@ public class AppointmentExcelServiceImpl implements AppointmentExcelService {
* @param fileName
* @return
*/
public
String
exportAndUploadToOss
(
Map
<
String
,
Object
>
data
,
String
ossObjectKey
,
String
fileName
)
{
public
String
exportAndUploadToOss
(
Map
<
String
,
Object
>
data
,
String
ossObjectKey
,
String
fileName
,
String
projectBizId
)
{
File
tempFile
=
null
;
File
processedFile
=
null
;
...
...
@@ -301,12 +301,13 @@ public class AppointmentExcelServiceImpl implements AppointmentExcelService {
@Override
public
String
exportAppointment
(
Map
<
String
,
Object
>
data
,
String
templateType
,
String
appointmentBizId
)
{
String
appointmentBizId
,
String
projectBizId
)
{
// 获取模板信息
FileProdDto
fileProdDto
=
iFileTemplateService
.
getFileProd
(
""
,
templateType
);
// 生成文件名
String
fileName
=
"预约信息_"
+
appointmentBizId
+
"_"
+
System
.
currentTimeMillis
()
+
".xlsx"
;
// 导出并上传到OSS
return
exportAndUploadToOss
(
data
,
fileProdDto
.
getFileKey
(),
fileName
);
return
exportAndUploadToOss
(
data
,
fileProdDto
.
getFileKey
(),
fileName
,
projectBizId
);
}
}
yd-oss-service/src/main/java/com/yd/oss/service/service/impl/ExcelExportServiceImpl.java
View file @
c5866e47
...
...
@@ -115,7 +115,8 @@ public class ExcelExportServiceImpl implements ExcelExportService {
fileName
,
// 生成的文件名
""
,
// 存储桶名称(空字符串表示使用默认存储桶)
""
,
// 上传用户标识(空字符串表示匿名或系统用户)
"excel"
// 文件分类类型,对应OSS文件夹目录
"excel"
,
// 文件分类类型,对应OSS文件夹目录
""
);
// 返回成功结果,包含文件URL和大小信息
...
...
yd-oss-service/src/main/java/com/yd/oss/service/service/impl/OssProviderServiceImpl.java
View file @
c5866e47
package
com
.
yd
.
oss
.
service
.
service
.
impl
;
import
com.alibaba.cloud.commons.lang.StringUtils
;
import
com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper
;
import
com.yd.common.exception.BusinessException
;
import
com.yd.oss.service.model.OssProvider
;
import
com.yd.oss.service.dao.OssProviderMapper
;
...
...
@@ -75,6 +77,14 @@ public class OssProviderServiceImpl extends ServiceImpl<OssProviderMapper, OssPr
return
provider
;
}
@Override
public
OssProvider
getProviderByBizId
(
String
providerBizId
)
{
return
baseMapper
.
selectOne
(
new
LambdaQueryWrapper
<
OssProvider
>()
.
eq
(
OssProvider:
:
getProviderBizId
,
providerBizId
)
.
last
(
" limit 1 "
)
);
}
/**
* 获取所有激活的OSS提供商
* @return
...
...
@@ -113,4 +123,24 @@ public class OssProviderServiceImpl extends ServiceImpl<OssProviderMapper, OssPr
public
boolean
deleteProvider
(
Long
id
)
{
return
ossProviderMapper
.
deleteById
(
id
)
>
0
;
}
/**
* 根据项目ID查询对应OSS服务商
* @param projectBizId
* @return
*/
@Override
public
OssProvider
getProviderByProjectId
(
String
projectBizId
)
{
if
(
StringUtils
.
isBlank
(
projectBizId
))
{
//项目ID空值,查询默认的服务商
return
baseMapper
.
selectOne
(
new
LambdaQueryWrapper
<
OssProvider
>()
.
eq
(
OssProvider:
:
getIsDefault
,
1
)
.
last
(
" limit 1 "
)
);
}
return
baseMapper
.
selectOne
(
new
LambdaQueryWrapper
<
OssProvider
>()
.
eq
(
OssProvider:
:
getProjectBizId
,
projectBizId
)
.
last
(
" limit 1 "
)
);
}
}
yd-oss-service/src/main/java/com/yd/oss/service/utils/OssUtils.java
0 → 100644
View file @
c5866e47
package
com
.
yd
.
oss
.
service
.
utils
;
import
com.yd.common.result.Result
;
import
com.yd.user.feign.client.sysproject.ApiSysProjectFeignClient
;
import
com.yd.user.feign.response.sysproject.ApiSysProjectDetailResponse
;
import
org.apache.commons.lang3.StringUtils
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Component
;
import
org.springframework.core.env.Environment
;
import
java.time.LocalDateTime
;
import
java.time.format.DateTimeFormatter
;
@Component
public
class
OssUtils
{
@Autowired
private
Environment
environment
;
@Autowired
private
ApiSysProjectFeignClient
apiSysProjectFeignClient
;
/**
* 获取通用文件路径的前缀
* @param projectBizId 项目ID
* @param env 环境变量(prod,test)如果不传系统获取
* @param originalFileName 原始文件名
* @param fileType(文件类型,文件扩展名)
* @return
*/
public
String
getFilePrefix
(
String
projectBizId
,
String
env
,
String
originalFileName
,
String
fileType
)
{
String
projectType
=
"pc"
;
if
(
StringUtils
.
isNotBlank
(
projectBizId
))
{
//通过项目ID查询项目类型
Result
<
ApiSysProjectDetailResponse
>
result
=
apiSysProjectFeignClient
.
detail
(
projectBizId
);
if
(
result
.
getData
()
!=
null
)
{
ApiSysProjectDetailResponse
response
=
result
.
getData
();
projectType
=
StringUtils
.
isNotBlank
(
response
.
getProjectType
())
?
response
.
getProjectType
()
:
"pc"
;
}
}
if
(
StringUtils
.
isBlank
(
env
))
{
env
=
getActiveEnv
();
}
return
projectType
+
"/"
+
env
+
"/"
+
FileUtil
.
generateFileKey
(
originalFileName
,
fileType
);
}
/**
* 获取分片文件路径的前缀
* @param projectBizId
* @param env
* @param env
* @return
*/
public
String
getShardFilePrefix
(
String
projectBizId
,
String
env
)
{
String
projectType
=
"pc"
;
if
(
StringUtils
.
isNotBlank
(
projectBizId
))
{
//通过项目ID查询项目类型
Result
<
ApiSysProjectDetailResponse
>
result
=
apiSysProjectFeignClient
.
detail
(
projectBizId
);
if
(
result
.
getData
()
!=
null
)
{
ApiSysProjectDetailResponse
response
=
result
.
getData
();
projectType
=
StringUtils
.
isNotBlank
(
response
.
getProjectType
())
?
response
.
getProjectType
()
:
"pc"
;
}
}
if
(
StringUtils
.
isBlank
(
env
))
{
env
=
getActiveEnv
();
}
return
projectType
+
"/"
+
env
+
"/large_file/uploads/"
+
LocalDateTime
.
now
().
format
(
DateTimeFormatter
.
ofPattern
(
"yyyy/MM/dd/"
));
}
private
String
getActiveEnv
()
{
String
[]
activeProfiles
=
environment
.
getActiveProfiles
();
return
activeProfiles
.
length
>
0
?
activeProfiles
[
0
]
:
"prod"
;
}
}
yd-oss-service/yd-oss-service.iml
View file @
c5866e47
...
...
@@ -77,8 +77,6 @@
<orderEntry
type=
"library"
name=
"Maven: org.springdoc:springdoc-openapi-webmvc-core:1.7.0"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: org.springdoc:springdoc-openapi-common:1.7.0"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: io.swagger.core.v3:swagger-core:2.2.9"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: jakarta.xml.bind:jakarta.xml.bind-api:2.3.3"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: jakarta.activation:jakarta.activation-api:1.2.2"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: io.swagger.core.v3:swagger-annotations:2.2.9"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: io.swagger.core.v3:swagger-models:2.2.9"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: org.webjars:swagger-ui:4.18.2"
level=
"project"
/>
...
...
@@ -130,7 +128,6 @@
<orderEntry
type=
"library"
name=
"Maven: org.springframework.cloud:spring-cloud-starter:3.1.1"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: org.springframework.security:spring-security-rsa:1.0.10.RELEASE"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: org.bouncycastle:bcpkix-jdk15on:1.68"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: org.bouncycastle:bcprov-jdk15on:1.69"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: org.springframework.cloud:spring-cloud-starter-loadbalancer:3.1.1"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: org.springframework.cloud:spring-cloud-loadbalancer:3.1.1"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: io.projectreactor.addons:reactor-extra:3.4.7"
level=
"project"
/>
...
...
@@ -178,22 +175,30 @@
<orderEntry
type=
"library"
name=
"Maven: io.github.openfeign:feign-slf4j:11.8"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: com.aliyun.oss:aliyun-sdk-oss:3.15.1"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: org.apache.httpcomponents:httpclient:4.5.13"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: org.apache.httpcomponents:httpcore:4.4.15"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: org.jdom:jdom2:2.0.6.1"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: org.codehaus.jettison:jettison:1.1"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: stax:stax-api:1.0.1"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: com.aliyun:aliyun-java-sdk-core:4.5.10"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: com.aliyun:aliyun-java-sdk-ram:3.1.0"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: com.aliyun:aliyun-java-sdk-kms:2.11.0"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: com.aliyun:aliyun-java-sdk-sts:3.0.0"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: com.aliyun:aliyun-java-sdk-core:4.6.0"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: com.google.code.gson:gson:2.8.9"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: org.apache.httpcomponents:httpcore:4.4.15"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: commons-logging:commons-logging:1.2"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: org.apache.commons:commons-lang3:3.14.0"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: javax.xml.bind:jaxb-api:2.3.1"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: javax.activation:javax.activation-api:1.2.0"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: org.jacoco:org.jacoco.agent:runtime:0.8.5"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: org.glassfish.jaxb:jaxb-runtime:2.3.6"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: jakarta.xml.bind:jakarta.xml.bind-api:2.3.3"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: org.glassfish.jaxb:txw2:2.3.6"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: com.sun.istack:istack-commons-runtime:3.0.12"
level=
"project"
/>
<orderEntry
type=
"library"
scope=
"RUNTIME"
name=
"Maven: com.sun.activation:jakarta.activation:1.2.2"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: org.bouncycastle:bcprov-jdk15on:1.69"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: org.jacoco:org.jacoco.agent:runtime:0.8.7"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: org.ini4j:ini4j:0.5.4"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: io.opentracing:opentracing-api:0.33.0"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: io.opentracing:opentracing-util:0.33.0"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: io.opentracing:opentracing-noop:0.33.0"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: com.aliyun:aliyun-java-sdk-ram:3.1.0"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: com.aliyun:aliyun-java-sdk-kms:2.11.0"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: org.apache.tomcat.embed:tomcat-embed-core:9.0.60"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: org.apache.tomcat:tomcat-annotations-api:9.0.60"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: com.documents4j:documents4j-local:1.1.12"
level=
"project"
/>
...
...
@@ -227,7 +232,6 @@
<orderEntry
type=
"library"
name=
"Maven: org.apache.xmlbeans:xmlbeans:5.1.1"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: cn.afterturn:easypoi-base:4.4.0"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: org.apache.poi:poi-ooxml-schemas:4.1.1"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: org.apache.commons:commons-lang3:3.14.0"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: ognl:ognl:3.2.6"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: org.javassist:javassist:3.20.0-GA"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: javax.validation:validation-api:2.0.1.Final"
level=
"project"
/>
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment