chore: 调整代码格式 (mvn compile)

This commit is contained in:
2025-08-14 22:31:15 +08:00
parent b1a3e20494
commit 84e7f60dd4
14 changed files with 241 additions and 95 deletions

View File

@@ -131,7 +131,8 @@ public class SaTokenConfiguration {
}).filter(Objects::nonNull).toList(); }).filter(Objects::nonNull).toList();
if (!additionalExcludes.isEmpty()) { if (!additionalExcludes.isEmpty()) {
// 合并现有的 excludes 和新扫描到的 // 合并现有的 excludes 和新扫描到的
String[] existingExcludes = Optional.ofNullable(properties.getSecurity().getExcludes()).orElse(new String[0]); String[] existingExcludes = Optional.ofNullable(properties.getSecurity().getExcludes())
.orElse(new String[0]);
String[] combinedExcludes = Stream.concat(Arrays.stream(existingExcludes), additionalExcludes.stream()) String[] combinedExcludes = Stream.concat(Arrays.stream(existingExcludes), additionalExcludes.stream())
.toArray(String[]::new); .toArray(String[]::new);
properties.getSecurity().setExcludes(combinedExcludes); properties.getSecurity().setExcludes(combinedExcludes);

View File

@@ -1,12 +1,12 @@
/* /*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved. * Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
* <p> *
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0; * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* <p> *
* http://www.gnu.org/licenses/lgpl.html * http://www.apache.org/licenses/LICENSE-2.0
* <p> *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

View File

@@ -1,3 +1,19 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package top.continew.admin.system.controller; package top.continew.admin.system.controller;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
@@ -47,8 +63,10 @@ public class MultipartUploadController {
*/ */
@Operation(summary = "上传分片", description = "上传单个分片") @Operation(summary = "上传分片", description = "上传单个分片")
@PostMapping("/part") @PostMapping("/part")
public MultipartUploadResp uploadPart(@RequestPart("file") MultipartFile file, @RequestParam("uploadId") String uploadId, public MultipartUploadResp uploadPart(@RequestPart("file") MultipartFile file,
@RequestParam("partNumber") Integer partNumber, @RequestParam("path") String path) { @RequestParam("uploadId") String uploadId,
@RequestParam("partNumber") Integer partNumber,
@RequestParam("path") String path) {
return multipartUploadService.uploadPart(file, uploadId, partNumber, path); return multipartUploadService.uploadPart(file, uploadId, partNumber, path);
} }
@@ -74,5 +92,4 @@ public class MultipartUploadController {
multipartUploadService.cancelMultipartUpload(uploadId); multipartUploadService.cancelMultipartUpload(uploadId);
} }
} }

View File

@@ -1,3 +1,19 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package top.continew.admin.system.dao; package top.continew.admin.system.dao;
import top.continew.admin.system.model.resp.file.FilePartInfo; import top.continew.admin.system.model.resp.file.FilePartInfo;

View File

@@ -1,12 +1,12 @@
/* /*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved. * Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
* <p> *
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0; * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* <p> *
* http://www.gnu.org/licenses/lgpl.html * http://www.apache.org/licenses/LICENSE-2.0
* <p> *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -95,7 +95,8 @@ public class RedisMultipartUploadDaoDaoImpl implements MultipartUploadDao {
try { try {
// 缓存初始化信息 // 缓存初始化信息
RedisUtils.set(key, JSONUtil.toJsonStr(initResp), Duration.ofHours(MultipartUploadConstants.DEFAULT_EXPIRE_HOURS)); RedisUtils.set(key, JSONUtil.toJsonStr(initResp), Duration
.ofHours(MultipartUploadConstants.DEFAULT_EXPIRE_HOURS));
// 缓存元数据 // 缓存元数据
if (metadata != null && !metadata.isEmpty()) { if (metadata != null && !metadata.isEmpty()) {

View File

@@ -1,3 +1,19 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package top.continew.admin.system.factory;/* package top.continew.admin.system.factory;/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved. * Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
* *
@@ -14,7 +30,6 @@ package top.continew.admin.system.factory;/*
* limitations under the License. * limitations under the License.
*/ */
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@@ -30,6 +45,7 @@ import java.util.concurrent.ConcurrentHashMap;
/** /**
* 存储处理器工厂 * 存储处理器工厂
* <p>按类型分发 StorageHandler</p> * <p>按类型分发 StorageHandler</p>
*
* @author KAI * @author KAI
* @since 2025/07/24 13:35 * @since 2025/07/24 13:35
*/ */

View File

@@ -1,3 +1,19 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package top.continew.admin.system.handler; package top.continew.admin.system.handler;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
@@ -30,7 +46,11 @@ public interface StorageHandler {
* @param file 文件对象 * @param file 文件对象
* @return {@link MultipartUploadResp} 分片上传结果 * @return {@link MultipartUploadResp} 分片上传结果
*/ */
MultipartUploadResp uploadPart(StorageDO storageDO, String path, String uploadId, Integer partNumber, MultipartFile file); MultipartUploadResp uploadPart(StorageDO storageDO,
String path,
String uploadId,
Integer partNumber,
MultipartFile file);
/** /**
* 合并分片 * 合并分片
@@ -38,7 +58,11 @@ public interface StorageHandler {
* @param storageDO 存储实体 * @param storageDO 存储实体
* @param uploadId 上传Id * @param uploadId 上传Id
*/ */
void completeMultipartUpload(StorageDO storageDO, List<MultipartUploadResp> parts, String path, String uploadId, boolean needVerify); void completeMultipartUpload(StorageDO storageDO,
List<MultipartUploadResp> parts,
String path,
String uploadId,
boolean needVerify);
/** /**
* 清楚分片 * 清楚分片

View File

@@ -64,7 +64,9 @@ public class LocalStorageHandler implements StorageHandler {
String parentPath = req.getParentPath(); String parentPath = req.getParentPath();
String fileName = req.getFileName(); String fileName = req.getFileName();
StrUtil.blankToDefault(parentPath, StrUtil.SLASH); StrUtil.blankToDefault(parentPath, StrUtil.SLASH);
String relativePath = StrUtil.endWith(parentPath, StrUtil.SLASH) ? parentPath + fileName : parentPath + StrUtil.SLASH + fileName; String relativePath = StrUtil.endWith(parentPath, StrUtil.SLASH)
? parentPath + fileName
: parentPath + StrUtil.SLASH + fileName;
try { try {
// 创建临时目录用于存储分片 // 创建临时目录用于存储分片
String tempDirPath = buildTempDirPath(bucket, uploadId); String tempDirPath = buildTempDirPath(bucket, uploadId);
@@ -93,7 +95,11 @@ public class LocalStorageHandler implements StorageHandler {
} }
@Override @Override
public MultipartUploadResp uploadPart(StorageDO storageDO, String path, String uploadId, Integer partNumber, MultipartFile file) { public MultipartUploadResp uploadPart(StorageDO storageDO,
String path,
String uploadId,
Integer partNumber,
MultipartFile file) {
try { try {
long size = file.getSize(); long size = file.getSize();
String bucket = storageDO.getBucketName(); String bucket = storageDO.getBucketName();
@@ -135,7 +141,11 @@ public class LocalStorageHandler implements StorageHandler {
} }
@Override @Override
public void completeMultipartUpload(StorageDO storageDO, List<MultipartUploadResp> parts, String path, String uploadId, boolean needVerify) { public void completeMultipartUpload(StorageDO storageDO,
List<MultipartUploadResp> parts,
String path,
String uploadId,
boolean needVerify) {
String bucket = storageDO.getBucketName(); // 本地存储中bucket是存储根路径 String bucket = storageDO.getBucketName(); // 本地存储中bucket是存储根路径
String tempDirPath = buildTempDirPath(bucket, uploadId); String tempDirPath = buildTempDirPath(bucket, uploadId);
@@ -206,10 +216,10 @@ public class LocalStorageHandler implements StorageHandler {
* @return 临时目录路径 * @return 临时目录路径
*/ */
private String buildTempDirPath(String bucket, String uploadId) { private String buildTempDirPath(String bucket, String uploadId) {
return StrUtil.appendIfMissing(bucket, File.separator) + MultipartUploadConstants.TEMP_DIR_NAME + File.separator + uploadId; return StrUtil
.appendIfMissing(bucket, File.separator) + MultipartUploadConstants.TEMP_DIR_NAME + File.separator + uploadId;
} }
/** /**
* 构建目标文件路径 * 构建目标文件路径
* *

View File

@@ -1,3 +1,19 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package top.continew.admin.system.handler.impl; package top.continew.admin.system.handler.impl;
import cn.hutool.core.io.FileUtil; import cn.hutool.core.io.FileUtil;
@@ -46,7 +62,9 @@ public class S3StorageHandler implements StorageHandler {
String fileName = req.getFileName(); String fileName = req.getFileName();
String contentType = req.getContentType(); String contentType = req.getContentType();
StrUtil.blankToDefault(parentPath, StrUtil.SLASH); StrUtil.blankToDefault(parentPath, StrUtil.SLASH);
String relativePath = StrUtil.endWith(parentPath, StrUtil.SLASH) ? parentPath + fileName : parentPath + StrUtil.SLASH + fileName; String relativePath = StrUtil.endWith(parentPath, StrUtil.SLASH)
? parentPath + fileName
: parentPath + StrUtil.SLASH + fileName;
fileService.createParentDir(parentPath, storageDO); fileService.createParentDir(parentPath, storageDO);
try { try {
@@ -85,14 +103,17 @@ public class S3StorageHandler implements StorageHandler {
log.info("S3初始化分片上传成功: uploadId={}, path={}", uploadId, relativePath); log.info("S3初始化分片上传成功: uploadId={}, path={}", uploadId, relativePath);
return result; return result;
} catch (Exception e) { } catch (Exception e) {
throw new BaseException("S3初始化分片上传失败: " + e.getMessage(), e); throw new BaseException("S3初始化分片上传失败: " + e.getMessage(), e);
} }
} }
@Override @Override
public MultipartUploadResp uploadPart(StorageDO storageDO, String path, String uploadId, Integer partNumber, MultipartFile file) { public MultipartUploadResp uploadPart(StorageDO storageDO,
String path,
String uploadId,
Integer partNumber,
MultipartFile file) {
try { try {
String bucket = storageDO.getBucketName(); String bucket = storageDO.getBucketName();
// 读取数据到内存(注意:实际使用时可能需要优化大文件处理) // 读取数据到内存(注意:实际使用时可能需要优化大文件处理)
@@ -125,13 +146,18 @@ public class S3StorageHandler implements StorageHandler {
result.setPartNumber(partNumber); result.setPartNumber(partNumber);
result.setSuccess(false); result.setSuccess(false);
result.setErrorMessage(e.getMessage()); result.setErrorMessage(e.getMessage());
log.error("S3上传分片失败: partNumber={} for key={} with uploadId={} errorMessage={}", partNumber, path, uploadId, e.getMessage()); log.error("S3上传分片失败: partNumber={} for key={} with uploadId={} errorMessage={}", partNumber, path, uploadId, e
.getMessage());
return result; return result;
} }
} }
@Override @Override
public void completeMultipartUpload(StorageDO storageDO, List<MultipartUploadResp> parts, String path, String uploadId, boolean needVerify) { public void completeMultipartUpload(StorageDO storageDO,
List<MultipartUploadResp> parts,
String path,
String uploadId,
boolean needVerify) {
if (path == null) { if (path == null) {
throw new BaseException("无效的uploadId: " + uploadId); throw new BaseException("无效的uploadId: " + uploadId);
} }
@@ -169,14 +195,13 @@ public class S3StorageHandler implements StorageHandler {
S3Client s3Client = s3ClientFactory.getClient(storageDO); S3Client s3Client = s3ClientFactory.getClient(storageDO);
// 列出所有未完成的分片上传 // 列出所有未完成的分片上传
ListMultipartUploadsRequest listRequest = ListMultipartUploadsRequest.builder() ListMultipartUploadsRequest listRequest = ListMultipartUploadsRequest.builder().bucket(bucket).build();
.bucket(bucket)
.build();
ListMultipartUploadsResponse listResponse = s3Client.listMultipartUploads(listRequest); ListMultipartUploadsResponse listResponse = s3Client.listMultipartUploads(listRequest);
// 查找匹配的上传任务 // 查找匹配的上传任务
Optional<MultipartUpload> targetUpload = listResponse.uploads().stream() Optional<MultipartUpload> targetUpload = listResponse.uploads()
.stream()
.filter(upload -> upload.uploadId().equals(uploadId)) .filter(upload -> upload.uploadId().equals(uploadId))
.findFirst(); .findFirst();
@@ -207,14 +232,17 @@ public class S3StorageHandler implements StorageHandler {
return StorageTypeEnum.OSS; return StorageTypeEnum.OSS;
} }
/** /**
* 列出已上传的分片 * 列出已上传的分片
*/ */
public List<MultipartUploadResp> listParts(String bucket, String path, String uploadId, S3Client s3Client) { public List<MultipartUploadResp> listParts(String bucket, String path, String uploadId, S3Client s3Client) {
try { try {
// 构建请求 // 构建请求
ListPartsRequest request = ListPartsRequest.builder().bucket(bucket).key(buildS3Key(path)).uploadId(uploadId).build(); ListPartsRequest request = ListPartsRequest.builder()
.bucket(bucket)
.key(buildS3Key(path))
.uploadId(uploadId)
.build();
// 获取分片列表 // 获取分片列表
ListPartsResponse response = s3Client.listParts(request); ListPartsResponse response = s3Client.listParts(request);

View File

@@ -116,5 +116,4 @@ public class MultipartUploadInitResp implements Serializable {
@Schema(description = "已上传分片编号集合") @Schema(description = "已上传分片编号集合")
private Set<Integer> uploadedPartNumbers; private Set<Integer> uploadedPartNumbers;
} }

View File

@@ -1,3 +1,19 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package top.continew.admin.system.service; package top.continew.admin.system.service;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;

View File

@@ -1,3 +1,19 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package top.continew.admin.system.service.impl; package top.continew.admin.system.service.impl;
import cn.hutool.core.io.FileUtil; import cn.hutool.core.io.FileUtil;
@@ -51,17 +67,18 @@ public class MultipartUploadServiceImpl implements MultipartUploadService {
// 后续可以增加storageCode参数 指定某个存储平台 当前设计是默认存储平台 // 后续可以增加storageCode参数 指定某个存储平台 当前设计是默认存储平台
StorageDO storageDO = storageService.getByCode(null); StorageDO storageDO = storageService.getByCode(null);
// 根据文件Md5查询当前存储平台是否初始化过分片 // 根据文件Md5查询当前存储平台是否初始化过分片
String uploadId = multipartUploadDao.getUploadIdByMd5(multiPartUploadInitReq String uploadId = multipartUploadDao.getUploadIdByMd5(multiPartUploadInitReq.getFileMd5());
.getFileMd5());
if (StrUtil.isNotBlank(uploadId)) { if (StrUtil.isNotBlank(uploadId)) {
MultipartUploadInitResp multipartUpload = multipartUploadDao.getMultipartUpload(uploadId); MultipartUploadInitResp multipartUpload = multipartUploadDao.getMultipartUpload(uploadId);
//对比存储平台和分片大小是否一致 一致则返回结果 //对比存储平台和分片大小是否一致 一致则返回结果
if (multipartUpload != null if (multipartUpload != null && multipartUpload.getPartSize()
&& multipartUpload.getPartSize().equals(MultipartUploadConstants.MULTIPART_UPLOAD_PART_SIZE) .equals(MultipartUploadConstants.MULTIPART_UPLOAD_PART_SIZE) && multipartUpload.getPlatform()
&& multipartUpload.getPlatform().equals(storageDO.getCode())) { .equals(storageDO.getCode())) {
// 获取已上传分片信息 // 获取已上传分片信息
List<FilePartInfo> fileParts = multipartUploadDao.getFileParts(uploadId); List<FilePartInfo> fileParts = multipartUploadDao.getFileParts(uploadId);
Set<Integer> partNumbers = fileParts.stream().map(FilePartInfo::getPartNumber).collect(Collectors.toSet()); Set<Integer> partNumbers = fileParts.stream()
.map(FilePartInfo::getPartNumber)
.collect(Collectors.toSet());
multipartUpload.setUploadedPartNumbers(partNumbers); multipartUpload.setUploadedPartNumbers(partNumbers);
return multipartUpload; return multipartUpload;
} }
@@ -71,7 +88,8 @@ public class MultipartUploadServiceImpl implements MultipartUploadService {
StorageHandler storageHandler = storageHandlerFactory.createHandler(storageDO.getType()); StorageHandler storageHandler = storageHandlerFactory.createHandler(storageDO.getType());
//文件元信息 //文件元信息
Map<String, String> metaData = multiPartUploadInitReq.getMetaData(); Map<String, String> metaData = multiPartUploadInitReq.getMetaData();
MultipartUploadInitResp multipartUploadInitResp = storageHandler.initMultipartUpload(storageDO, multiPartUploadInitReq); MultipartUploadInitResp multipartUploadInitResp = storageHandler
.initMultipartUpload(storageDO, multiPartUploadInitReq);
// 缓存文件信息,md5和uploadId映射 // 缓存文件信息,md5和uploadId映射
multipartUploadDao.setMultipartUpload(multipartUploadInitResp.getUploadId(), multipartUploadInitResp, metaData); multipartUploadDao.setMultipartUpload(multipartUploadInitResp.getUploadId(), multipartUploadInitResp, metaData);
multipartUploadDao.setMd5Mapping(multiPartUploadInitReq.getFileMd5(), multipartUploadInitResp.getUploadId()); multipartUploadDao.setMd5Mapping(multiPartUploadInitReq.getFileMd5(), multipartUploadInitResp.getUploadId());