From 95a97ab06ccedcf9731f7dfb0e29d95ec2cd8d4f Mon Sep 17 00:00:00 2001 From: AprilWind <2100166581@qq.com> Date: Mon, 15 Apr 2024 12:14:47 +0800 Subject: [PATCH 01/23] =?UTF-8?q?update=20oss=E5=A2=9E=E5=8A=A0=E5=88=86?= =?UTF-8?q?=E7=89=87=E4=B8=8A=E4=BC=A0=E5=B7=A5=E5=85=B7=EF=BC=8C=E4=B8=B4?= =?UTF-8?q?=E6=97=B6url=E5=B7=A5=E5=85=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dromara/common/oss/core/OssClient.java | 140 +++++++++++++++++- .../common/oss/entity/PartUploadResult.java | 25 ++++ .../common/oss/entity/UploadResult.java | 12 ++ 3 files changed, 174 insertions(+), 3 deletions(-) create mode 100644 ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/entity/PartUploadResult.java diff --git a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/core/OssClient.java b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/core/OssClient.java index eb1656c06..d30b21d9e 100644 --- a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/core/OssClient.java +++ b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/core/OssClient.java @@ -7,6 +7,7 @@ import org.dromara.common.core.utils.DateUtils; import org.dromara.common.core.utils.StringUtils; import org.dromara.common.core.utils.file.FileUtils; import org.dromara.common.oss.constant.OssConstant; +import org.dromara.common.oss.entity.PartUploadResult; import org.dromara.common.oss.entity.UploadResult; import org.dromara.common.oss.enumd.AccessPolicyType; import org.dromara.common.oss.enumd.PolicyType; @@ -19,7 +20,9 @@ import software.amazon.awssdk.core.async.BlockingInputStreamAsyncRequestBody; import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.s3.S3AsyncClient; import software.amazon.awssdk.services.s3.S3Configuration; +import software.amazon.awssdk.services.s3.model.CompletedPart; import software.amazon.awssdk.services.s3.model.NoSuchBucketException; +import software.amazon.awssdk.services.s3.model.Part; import software.amazon.awssdk.services.s3.model.S3Exception; import software.amazon.awssdk.services.s3.presigner.S3Presigner; import software.amazon.awssdk.transfer.s3.S3TransferManager; @@ -35,6 +38,8 @@ import java.net.URL; import java.nio.file.Files; import java.nio.file.Path; import java.time.Duration; +import java.util.List; +import java.util.stream.Collectors; /** * S3 存储协议 所有兼容S3协议的云厂商均支持 @@ -274,10 +279,11 @@ public class OssClient { } /** - * 获取私有URL链接 + * 生成预签名的私有对象获取 URL * - * @param objectKey 对象KEY - * @param second 授权时间 + * @param objectKey 对象键(Object Key) + * @param second 签名持续时间(秒) + * @return 预签名 URL 字符串 */ public String getPrivateUrl(String objectKey, Integer second) { // 使用 AWS S3 预签名 URL 的生成器 获取对象的预签名 URL @@ -292,6 +298,122 @@ public class OssClient { return url.toString(); } + /** + * 生成预签名的私有上传 URL + * + * @param key 对象键(Object Key) + * @param md5Digest 内容的 MD5 摘要,如果有的话 + * @param second 签名持续时间(秒) + * @return 上传结果对象 + */ + public UploadResult putPrivateUrl(String key, String md5Digest, Integer second) { + URL url = presigner.presignPutObject( + x -> x.signatureDuration(Duration.ofSeconds(second)) + .putObjectRequest( + y -> y.bucket(properties.getBucketName()) + .key(key) + .contentMD5(StringUtils.isNotEmpty(md5Digest) ? md5Digest : null) + .build() + ).build() + ).url(); + return UploadResult.builder().url(getUrl() + StringUtils.SLASH + key).filename(key).privateUrl(url.toString()).build(); + } + + /** + * 创建分片上传任务 + * + * @param key 对象的键(Object Key) + * @return 包含上传 ID 的 UploadResult 对象 + */ + public UploadResult initiateMultipartUpload(String key) { + String uploadId = client.createMultipartUpload( + x -> x.bucket(properties.getBucketName()) + .key(key) + .build() + ).join().uploadId(); + return UploadResult.builder().url(getUrl() + StringUtils.SLASH + key).filename(key).uploadId(uploadId).build(); + } + + /** + * 生成预签名的分片上传 URL + * + * @param key 对象键(Object Key) + * @param uploadId 分片上传任务的 Upload ID + * @param partNumber 分片编号 + * @param second 签名持续时间(秒) + * @return 预签名 URL 字符串 + */ + public String uploadPartFutures(String key, String uploadId, Integer partNumber, Integer second) { + URL url = presigner.presignUploadPart( + x -> x.signatureDuration(Duration.ofSeconds(second)) + .uploadPartRequest( + y -> y.bucket(properties.getBucketName()) + .key(key) + .uploadId(uploadId) + .partNumber(partNumber) + .build() + ).build() + ).url(); + return url.toString(); + } + + /** + * 获取指定对象分片上传的分片列表 + * + * @param key 对象的键(Object Key) + * @param uploadId 分片上传任务的 Upload ID + * @param maxParts 最大返回的分片数(默认为1000) + * @param partNumberMarker 分片编号的标记,用于分页查询(默认为0,表示从第一个分片开始查询) + * @return 包含分片上传结果信息的 PartUploadResult 对象列表 + */ + public List listParts(String key, String uploadId, Integer maxParts, Integer partNumberMarker) { + List parts = client.listParts( + x -> x.bucket(properties.getBucketName()) + .key(key) + .uploadId(uploadId) + .maxParts(maxParts != null ? maxParts : 1000) + .partNumberMarker(partNumberMarker != null ? partNumberMarker : 0) + .build()).join().parts(); + return parts.stream() + .map(x -> PartUploadResult.builder() + .partNumber(x.partNumber()) + .eTag(x.eTag()) + .build()) + .collect(Collectors.toList()); + } + + /** + * 完成分片上传任务 + * + * @param key 对象的键(Object Key) + * @param uploadId 分片上传任务的 Upload ID + * @param partUploadResults 已完成的分片列表 + * @return 包含上传结果信息的 UploadResult 对象 + */ + public UploadResult completeMultipartUpload(String key, String uploadId, List partUploadResults) { + List completedParts = partUploadResults.stream() + .map(x -> CompletedPart.builder() + .partNumber(x.getPartNumber()) + .eTag(x.getETag()) + .build()) + .collect(Collectors.toList()); + try { + String eTag = client.completeMultipartUpload( + x -> x.bucket(properties.getBucketName()) + .key(key) + .uploadId(uploadId) + .multipartUpload(y -> y.parts(completedParts) + .build()) + .build() + ).join().eTag(); + // 提取上传结果中的 ETag,并构建一个自定义的 UploadResult 对象 + return UploadResult.builder().url(getUrl() + StringUtils.SLASH + key).filename(key).eTag(eTag).build(); + } catch (Exception e) { + // 捕获异常并抛出自定义异常 + throw new OssException("上传文件失败,请检查配置信息:[" + e.getMessage() + "]"); + } + } + /** * 上传 byte[] 数据到 Amazon S3,使用指定的后缀构造对象键。 * @@ -329,6 +451,18 @@ public class OssClient { return upload(file.toPath(), getPath(properties.getPrefix(), suffix), null); } + /** + * 并生成私有上传预签名 URL + * + * @param suffix 文件后缀 + * @param md5Digest 内容的 MD5 摘要,如果有的话 + * @param second 预签名 URL 的有效期(秒) + * @return 上传结果对象 + */ + public UploadResult uploadSuffix(String suffix, String md5Digest, Integer second) { + return putPrivateUrl(getPath(properties.getPrefix(), suffix), md5Digest, second); + } + /** * 获取文件输入流 * diff --git a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/entity/PartUploadResult.java b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/entity/PartUploadResult.java new file mode 100644 index 000000000..dee893df2 --- /dev/null +++ b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/entity/PartUploadResult.java @@ -0,0 +1,25 @@ +package org.dromara.common.oss.entity; + +import lombok.Builder; +import lombok.Data; + +/** + * 上传部件返回体 + * + * @author AprilWind + */ +@Data +@Builder +public class PartUploadResult { + + /** + * 新上传部件的部件号 + */ + private Integer partNumber; + + /** + * 从上传部分的内容生成的实体标签 + */ + private String eTag; + +} diff --git a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/entity/UploadResult.java b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/entity/UploadResult.java index 81a18e62a..4c9c32a56 100644 --- a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/entity/UploadResult.java +++ b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/entity/UploadResult.java @@ -27,4 +27,16 @@ public class UploadResult { */ private String eTag; + /** + * 用于分片上传任务的 Upload ID + * 在初始化分片上传时获取,并在后续的分片上传和完成上传过程中使用 + */ + private String uploadId; + + /** + * 用于私有预签名 URL + * 用于上传文件或分片的预签名 URL,确保文件或分片在上传时具有私有访问权限 + */ + private String privateUrl; + } From bd8994f0debca298b16568ed6be858fa7d45a8e9 Mon Sep 17 00:00:00 2001 From: AprilWind <2100166581@qq.com> Date: Mon, 15 Apr 2024 12:37:47 +0800 Subject: [PATCH 02/23] =?UTF-8?q?update=20oss=E5=B7=A5=E5=85=B7=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E6=8A=A5=E9=94=99=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dromara/common/oss/core/OssClient.java | 52 ++++++++++++------- 1 file changed, 33 insertions(+), 19 deletions(-) diff --git a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/core/OssClient.java b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/core/OssClient.java index d30b21d9e..ccd09b04d 100644 --- a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/core/OssClient.java +++ b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/core/OssClient.java @@ -1,5 +1,6 @@ package org.dromara.common.oss.core; +import cn.hutool.core.collection.CollUtil; import cn.hutool.core.io.IoUtil; import cn.hutool.core.util.IdUtil; import org.dromara.common.core.constant.Constants; @@ -326,12 +327,17 @@ public class OssClient { * @return 包含上传 ID 的 UploadResult 对象 */ public UploadResult initiateMultipartUpload(String key) { - String uploadId = client.createMultipartUpload( - x -> x.bucket(properties.getBucketName()) - .key(key) - .build() - ).join().uploadId(); - return UploadResult.builder().url(getUrl() + StringUtils.SLASH + key).filename(key).uploadId(uploadId).build(); + try { + String uploadId = client.createMultipartUpload( + x -> x.bucket(properties.getBucketName()) + .key(key) + .build() + ).join().uploadId(); + return UploadResult.builder().url(getUrl() + StringUtils.SLASH + key).filename(key).uploadId(uploadId).build(); + } catch (Exception e) { + // 捕获异常并抛出自定义异常 + throw new OssException("创建分片上传任务失败,请检查配置信息:[" + e.getMessage() + "]"); + } } /** @@ -367,19 +373,24 @@ public class OssClient { * @return 包含分片上传结果信息的 PartUploadResult 对象列表 */ public List listParts(String key, String uploadId, Integer maxParts, Integer partNumberMarker) { - List parts = client.listParts( - x -> x.bucket(properties.getBucketName()) - .key(key) - .uploadId(uploadId) - .maxParts(maxParts != null ? maxParts : 1000) - .partNumberMarker(partNumberMarker != null ? partNumberMarker : 0) - .build()).join().parts(); - return parts.stream() - .map(x -> PartUploadResult.builder() - .partNumber(x.partNumber()) - .eTag(x.eTag()) - .build()) - .collect(Collectors.toList()); + try { + List parts = client.listParts( + x -> x.bucket(properties.getBucketName()) + .key(key) + .uploadId(uploadId) + .maxParts(maxParts != null ? maxParts : 1000) + .partNumberMarker(partNumberMarker != null ? partNumberMarker : 0) + .build()).join().parts(); + return parts.stream() + .map(x -> PartUploadResult.builder() + .partNumber(x.partNumber()) + .eTag(x.eTag()) + .build()) + .collect(Collectors.toList()); + } catch (Exception e) { + // 捕获异常并抛出自定义异常 + throw new OssException("获取分片列表失败,请检查配置信息:[" + e.getMessage() + "]"); + } } /** @@ -391,6 +402,9 @@ public class OssClient { * @return 包含上传结果信息的 UploadResult 对象 */ public UploadResult completeMultipartUpload(String key, String uploadId, List partUploadResults) { + if (CollUtil.isEmpty(partUploadResults)) { + throw new OssException("分片列表不能为空"); + } List completedParts = partUploadResults.stream() .map(x -> CompletedPart.builder() .partNumber(x.getPartNumber()) From 27aca5d5b2e9332b9e21a1c28662080ab75f36b3 Mon Sep 17 00:00:00 2001 From: AprilWind <2100166581@qq.com> Date: Mon, 15 Apr 2024 14:29:59 +0800 Subject: [PATCH 03/23] =?UTF-8?q?update=20oss=E5=B7=A5=E5=85=B7=E7=BB=9F?= =?UTF-8?q?=E4=B8=80=E6=A0=BC=E5=BC=8F=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dromara/common/oss/core/OssClient.java | 22 ++++++++++--------- .../common/oss/entity/PartUploadResult.java | 2 +- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/core/OssClient.java b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/core/OssClient.java index ccd09b04d..8d0a1821d 100644 --- a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/core/OssClient.java +++ b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/core/OssClient.java @@ -282,7 +282,7 @@ public class OssClient { /** * 生成预签名的私有对象获取 URL * - * @param objectKey 对象键(Object Key) + * @param objectKey 在 Amazon S3 中的对象键 * @param second 签名持续时间(秒) * @return 预签名 URL 字符串 */ @@ -302,7 +302,7 @@ public class OssClient { /** * 生成预签名的私有上传 URL * - * @param key 对象键(Object Key) + * @param key 在 Amazon S3 中的对象键 * @param md5Digest 内容的 MD5 摘要,如果有的话 * @param second 签名持续时间(秒) * @return 上传结果对象 @@ -323,8 +323,8 @@ public class OssClient { /** * 创建分片上传任务 * - * @param key 对象的键(Object Key) - * @return 包含上传 ID 的 UploadResult 对象 + * @param key 在 Amazon S3 中的对象键 + * @return 包含上传后的文件信息 */ public UploadResult initiateMultipartUpload(String key) { try { @@ -343,13 +343,14 @@ public class OssClient { /** * 生成预签名的分片上传 URL * - * @param key 对象键(Object Key) + * @param key 在 Amazon S3 中的对象键 * @param uploadId 分片上传任务的 Upload ID - * @param partNumber 分片编号 + * @param partNumber 分片编号(从1开始递增) + * @param md5Digest 内容的 MD5 摘要,如果有的话 * @param second 签名持续时间(秒) * @return 预签名 URL 字符串 */ - public String uploadPartFutures(String key, String uploadId, Integer partNumber, Integer second) { + public String uploadPartFutures(String key, String uploadId, Integer partNumber, String md5Digest, Integer second) { URL url = presigner.presignUploadPart( x -> x.signatureDuration(Duration.ofSeconds(second)) .uploadPartRequest( @@ -357,6 +358,7 @@ public class OssClient { .key(key) .uploadId(uploadId) .partNumber(partNumber) + .contentMD5(StringUtils.isNotEmpty(md5Digest) ? md5Digest : null) .build() ).build() ).url(); @@ -366,7 +368,7 @@ public class OssClient { /** * 获取指定对象分片上传的分片列表 * - * @param key 对象的键(Object Key) + * @param key 在 Amazon S3 中的对象键 * @param uploadId 分片上传任务的 Upload ID * @param maxParts 最大返回的分片数(默认为1000) * @param partNumberMarker 分片编号的标记,用于分页查询(默认为0,表示从第一个分片开始查询) @@ -396,10 +398,10 @@ public class OssClient { /** * 完成分片上传任务 * - * @param key 对象的键(Object Key) + * @param key 在 Amazon S3 中的对象键 * @param uploadId 分片上传任务的 Upload ID * @param partUploadResults 已完成的分片列表 - * @return 包含上传结果信息的 UploadResult 对象 + * @return 包含上传后的文件信息 */ public UploadResult completeMultipartUpload(String key, String uploadId, List partUploadResults) { if (CollUtil.isEmpty(partUploadResults)) { diff --git a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/entity/PartUploadResult.java b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/entity/PartUploadResult.java index dee893df2..a00408925 100644 --- a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/entity/PartUploadResult.java +++ b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/entity/PartUploadResult.java @@ -13,7 +13,7 @@ import lombok.Data; public class PartUploadResult { /** - * 新上传部件的部件号 + * 分片编号(从1开始递增) */ private Integer partNumber; From 0131163368951a6c3a1e87ca257d61cf995a31ed Mon Sep 17 00:00:00 2001 From: AprilWind <2100166581@qq.com> Date: Mon, 15 Apr 2024 15:15:17 +0800 Subject: [PATCH 04/23] =?UTF-8?q?update=20oss=E5=B7=A5=E5=85=B7=E5=AE=8C?= =?UTF-8?q?=E6=88=90=E5=88=86=E7=89=87=E4=B8=8A=E4=BC=A0=E5=88=97=E8=A1=A8?= =?UTF-8?q?=E5=BF=85=E9=A1=BB=E6=98=AF=E5=94=AF=E4=B8=80=E4=B8=94=E6=8C=89?= =?UTF-8?q?=E7=85=A7=E9=80=92=E5=A2=9E=E9=A1=BA=E5=BA=8F=E6=8E=92=E5=88=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/org/dromara/common/oss/core/OssClient.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/core/OssClient.java b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/core/OssClient.java index 8d0a1821d..42edf2ae2 100644 --- a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/core/OssClient.java +++ b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/core/OssClient.java @@ -400,7 +400,7 @@ public class OssClient { * * @param key 在 Amazon S3 中的对象键 * @param uploadId 分片上传任务的 Upload ID - * @param partUploadResults 已完成的分片列表 + * @param partUploadResults 已完成的分片列表(必须是唯一且按照递增顺序排列,严格检查是否漏传) * @return 包含上传后的文件信息 */ public UploadResult completeMultipartUpload(String key, String uploadId, List partUploadResults) { From 6cc2eab3d74d2111ad89310741fc7763355ab080 Mon Sep 17 00:00:00 2001 From: AprilWind <2100166581@qq.com> Date: Wed, 24 Apr 2024 10:57:12 +0800 Subject: [PATCH 05/23] =?UTF-8?q?add=20=E6=96=B0=E5=A2=9E=E5=88=86?= =?UTF-8?q?=E7=89=87=E4=B8=8A=E4=BC=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dromara/common/oss/core/OssClient.java | 12 ++- .../controller/system/SysOssController.java | 54 ++++++++++- .../dromara/system/domain/bo/MultipartBo.java | 97 +++++++++++++++++++ .../dromara/system/domain/vo/MultipartVo.java | 68 +++++++++++++ .../system/service/ISysOssService.java | 36 ++++++- .../service/impl/SysOssServiceImpl.java | 73 ++++++++++++++ 6 files changed, 334 insertions(+), 6 deletions(-) create mode 100644 ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/MultipartBo.java create mode 100644 ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/MultipartVo.java diff --git a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/core/OssClient.java b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/core/OssClient.java index 42edf2ae2..9eae4376d 100644 --- a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/core/OssClient.java +++ b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/core/OssClient.java @@ -333,7 +333,7 @@ public class OssClient { .key(key) .build() ).join().uploadId(); - return UploadResult.builder().url(getUrl() + StringUtils.SLASH + key).filename(key).uploadId(uploadId).build(); + return UploadResult.builder().filename(key).uploadId(uploadId).build(); } catch (Exception e) { // 捕获异常并抛出自定义异常 throw new OssException("创建分片上传任务失败,请检查配置信息:[" + e.getMessage() + "]"); @@ -479,6 +479,16 @@ public class OssClient { return putPrivateUrl(getPath(properties.getPrefix(), suffix), md5Digest, second); } + /** + * 创建分片上传任务 + * + * @param suffix 对象键的后缀 + * @return 包含上传后的文件信息 + */ + public UploadResult initiateMultipart(String suffix){ + return initiateMultipartUpload(getPath(properties.getPrefix(), suffix)); + } + /** * 获取文件输入流 * diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysOssController.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysOssController.java index 73ada3b84..269d67d1b 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysOssController.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysOssController.java @@ -3,20 +3,26 @@ package org.dromara.system.controller.system; import cn.dev33.satoken.annotation.SaCheckPermission; import cn.hutool.core.util.ObjectUtil; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.Size; +import lombok.RequiredArgsConstructor; import org.dromara.common.core.domain.R; +import org.dromara.common.core.validate.AddGroup; +import org.dromara.common.core.validate.EditGroup; import org.dromara.common.core.validate.QueryGroup; -import org.dromara.common.web.core.BaseController; import org.dromara.common.log.annotation.Log; import org.dromara.common.log.enums.BusinessType; import org.dromara.common.mybatis.core.page.PageQuery; import org.dromara.common.mybatis.core.page.TableDataInfo; +import org.dromara.common.web.core.BaseController; +import org.dromara.system.domain.bo.MultipartBo; import org.dromara.system.domain.bo.SysOssBo; +import org.dromara.system.domain.vo.MultipartVo; import org.dromara.system.domain.vo.SysOssUploadVo; import org.dromara.system.domain.vo.SysOssVo; import org.dromara.system.service.ISysOssService; -import jakarta.servlet.http.HttpServletResponse; -import jakarta.validation.constraints.NotEmpty; -import lombok.RequiredArgsConstructor; import org.springframework.http.MediaType; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -105,4 +111,44 @@ public class SysOssController extends BaseController { return toAjax(ossService.deleteWithValidByIds(List.of(ossIds), true)); } + /** + * 初始化分片上传任务 + * + * @param originalName 文件原名 + */ + @SaCheckPermission("system:oss:multipart") + @PostMapping(value = "/multipart/initiate") + public R initiateMultipart(@Size(min = 2, max = 255, message = "文件原名长度必须在2到255之间") + @NotBlank(message = "文件原名不能为空") String originalName) { + return R.ok(ossService.initiateMultipart(originalName)); + } + + /** + * 上传分段 + */ + @SaCheckPermission("system:oss:multipart") + @PostMapping(value = "/multipart/upload") + public R uploadPart(@Validated(AddGroup.class) @RequestBody MultipartBo multipartBo) { + return R.ok(ossService.uploadPart(multipartBo)); + } + + /** + * 查询上传分段进度 + */ + @SaCheckPermission("system:oss:multipart") + @PostMapping(value = "/multipart/list") + public R uploadPartList(@Validated(QueryGroup.class) @RequestBody MultipartBo multipartBo) { + return R.ok(ossService.uploadPartList(multipartBo)); + } + + /** + * 合并分段文件 + */ + @SaCheckPermission("system:oss:multipart") + @Log(title = "OSS对象存储-分片", businessType = BusinessType.INSERT) + @PostMapping(value = "/multipart/complete") + public R completeMultipartUpload(@Validated(EditGroup.class) @RequestBody MultipartBo multipartBo) { + return R.ok(ossService.completeMultipartUpload(multipartBo)); + } + } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/MultipartBo.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/MultipartBo.java new file mode 100644 index 000000000..760549959 --- /dev/null +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/MultipartBo.java @@ -0,0 +1,97 @@ +package org.dromara.system.domain.bo; + +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; +import lombok.Data; +import org.dromara.common.core.validate.AddGroup; +import org.dromara.common.core.validate.EditGroup; +import org.dromara.common.core.validate.QueryGroup; + +import java.io.Serial; +import java.io.Serializable; +import java.util.List; + +/** + * @author AprilWind + */ +@Data +public class MultipartBo implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 文件名 + */ + @NotBlank(message = "文件名不能为空", groups = {QueryGroup.class, AddGroup.class, EditGroup.class}) + private String filename; + + /** + * 用于分片上传任务的 Upload ID + * 在初始化分片上传时获取,并在后续的分片上传和完成上传过程中使用 + */ + @NotBlank(message = "上传任务ID不能为空", groups = {QueryGroup.class, AddGroup.class, EditGroup.class}) + private String uploadId; + + /** + * 分片编号(从1开始递增) + */ + @NotNull(message = "分片编号不能为空", groups = AddGroup.class) + @Size(min = 1, max = 10000, message = "分片编号必须介于1和10,000之间", groups = AddGroup.class) + private Integer partNumber; + + /** + * 内容的 MD5 摘要 + */ + @Size(max = 255, message = "内容的 MD5 摘要,如果有的话不能超过255", groups = AddGroup.class) + private String md5Digest; + + /** + * 最大返回的分片数(默认为1000,最大值1000) + * 最多分片一万,一次性返回会造成前端性能问题,需要前端多次校验 + */ + @NotNull(message = "最大返回的分片数不能为空", groups = QueryGroup.class) + private Integer maxParts; + + /** + * 分片编号的标记,用于分页查询(默认为0,表示从第一个分片开始查询) + */ + @NotNull(message = "分片编号的标记不能为空", groups = QueryGroup.class) + private Integer partNumberMarker; + + /** + * 原名 + */ + @NotBlank(message = "原名不能为空", groups = EditGroup.class) + @Size(min = 2, max = 255, message = "文件原名长度必须在2到255之间", groups = EditGroup.class) + private String originalName; + + /** + * 已上传列表(最大长度一万) + * 必须是唯一且按照递增顺序排列,严格检查是否漏传 + */ + @NotNull(message = "已上传列表不能为空") + @Size(min = 2, max = 10000, message = "已上传列表长度必须在2到10000之间", groups = EditGroup.class) + private List partUploadList; + + @Data + public static class PartUploadResult implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 分片编号(从1开始递增) + */ + @NotNull(message = "分片编号不能为空", groups = EditGroup.class) + @Size(min = 1, max = 10000, message = "分片编号必须介于1和10,000之间", groups = EditGroup.class) + private Integer partNumber; + + /** + * 从上传部分的内容生成的实体标签 + */ + @NotBlank(message = "实体标签不能为空", groups = EditGroup.class) + private String eTag; + } +} diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/MultipartVo.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/MultipartVo.java new file mode 100644 index 000000000..1dc9f5266 --- /dev/null +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/MultipartVo.java @@ -0,0 +1,68 @@ +package org.dromara.system.domain.vo; + +import io.github.linpeilie.annotations.AutoMapper; +import lombok.AllArgsConstructor; +import lombok.Data; +import org.dromara.system.domain.SysOss; + +import java.io.Serial; +import java.io.Serializable; +import java.util.List; + +/** + * @author AprilWind + */ +@Data +@AutoMapper(target = SysOss.class) +public class MultipartVo implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 文件名 + */ + private String filename; + + /** + * 用于分片上传任务的 Upload ID + * 在初始化分片上传时获取,并在后续的分片上传和完成上传过程中使用 + */ + private String uploadId; + + /** + * 分片编号(从1开始递增) + */ + private Integer partNumber; + + /** + * 用于私有预签名 URL + * 用于上传文件或分片的预签名 URL,确保文件或分片在上传时具有私有访问权限 + */ + private String privateUrl; + + /** + * 已上传列表(最大长度一千) + * 必须是唯一且按照递增顺序排列,严格检查是否漏传 + */ + private List partUploadList; + + @Data + @AllArgsConstructor + public static class PartUploadResult implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 分片编号(从1开始递增) + */ + private Integer partNumber; + + /** + * 从上传部分的内容生成的实体标签 + */ + private String eTag; + } + +} diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysOssService.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysOssService.java index 057c068ce..f7c8adcd7 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysOssService.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysOssService.java @@ -1,10 +1,12 @@ package org.dromara.system.service; +import jakarta.servlet.http.HttpServletResponse; import org.dromara.common.mybatis.core.page.PageQuery; import org.dromara.common.mybatis.core.page.TableDataInfo; +import org.dromara.system.domain.bo.MultipartBo; import org.dromara.system.domain.bo.SysOssBo; +import org.dromara.system.domain.vo.MultipartVo; import org.dromara.system.domain.vo.SysOssVo; -import jakarta.servlet.http.HttpServletResponse; import org.springframework.web.multipart.MultipartFile; import java.io.File; @@ -77,4 +79,36 @@ public interface ISysOssService { */ Boolean deleteWithValidByIds(Collection ids, Boolean isValid); + /** + * 初始化分片上传任务 + * + * @param originalName 文件原名 + * @return 分片上传对象信息 + */ + MultipartVo initiateMultipart(String originalName); + + /** + * 上传文件的分段(分片上传) + * + * @param multipartBo SysOssMultipartBo 分段上传的参数对象 + * @return SysOssMultipartVo 分片上传成功后的对象信息 + */ + MultipartVo uploadPart(MultipartBo multipartBo); + + /** + * 获取上传分段进度 + * + * @param multipartBo 分片上传对象信息 + * @return 分片上传对象信息 + */ + MultipartVo uploadPartList(MultipartBo multipartBo); + + /** + * 合并分段 + * + * @param multipartBo 分片上传对象信息 + * @return OSS对象存储视图对象 + */ + SysOssVo completeMultipartUpload(MultipartBo multipartBo); + } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java index 1df221c32..d7dc49e1e 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java @@ -19,11 +19,14 @@ import org.dromara.common.core.utils.file.FileUtils; import org.dromara.common.mybatis.core.page.PageQuery; import org.dromara.common.mybatis.core.page.TableDataInfo; import org.dromara.common.oss.core.OssClient; +import org.dromara.common.oss.entity.PartUploadResult; import org.dromara.common.oss.entity.UploadResult; import org.dromara.common.oss.enumd.AccessPolicyType; import org.dromara.common.oss.factory.OssFactory; import org.dromara.system.domain.SysOss; +import org.dromara.system.domain.bo.MultipartBo; import org.dromara.system.domain.bo.SysOssBo; +import org.dromara.system.domain.vo.MultipartVo; import org.dromara.system.domain.vo.SysOssVo; import org.dromara.system.mapper.SysOssMapper; import org.dromara.system.service.ISysOssService; @@ -40,6 +43,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; /** * 文件上传 服务层实现 @@ -237,6 +241,74 @@ public class SysOssServiceImpl implements ISysOssService, OssService { return baseMapper.deleteBatchIds(ids) > 0; } + /** + * 初始化分片上传任务 + * + * @param originalName 文件原名 + * @return 分片上传对象信息 + */ + @Override + public MultipartVo initiateMultipart(String originalName) { + String suffix = StringUtils.substring(originalName, originalName.lastIndexOf("."), originalName.length()); + OssClient storage = OssFactory.instance(); + UploadResult uploadResult = storage.initiateMultipart(suffix); + return MapstructUtils.convert(uploadResult, MultipartVo.class); + } + + /** + * 上传文件的分段(分片上传) + * + * @param multipartBo MultipartBo 分段上传的参数对象 + * @return MultipartVo 分片上传成功后的对象信息 + */ + @Override + public MultipartVo uploadPart(MultipartBo multipartBo) { + OssClient storage = OssFactory.instance(); + String privateUrl = storage.uploadPartFutures(multipartBo.getFilename(), multipartBo.getUploadId(), multipartBo.getPartNumber(), multipartBo.getMd5Digest(), 10800); + MultipartVo multipartVo = MapstructUtils.convert(multipartBo, MultipartVo.class); + multipartVo.setPrivateUrl(privateUrl); + return multipartVo; + } + + /** + * 获取上传分段进度 + * + * @param multipartBo 分片上传对象信息 + * @return 分片上传对象信息 + */ + @Override + public MultipartVo uploadPartList(MultipartBo multipartBo) { + OssClient storage = OssFactory.instance(); + List listParts = storage.listParts(multipartBo.getFilename(), multipartBo.getUploadId(), multipartBo.getMaxParts(), multipartBo.getPartNumberMarker()); + MultipartVo multipartVo = MapstructUtils.convert(multipartBo, MultipartVo.class); + multipartVo.setPartUploadList(listParts.stream() + .map(x -> new MultipartVo.PartUploadResult(x.getPartNumber(), x.getETag())) + .collect(Collectors.toList())); + return multipartVo; + } + + /** + * 合并分段 + * + * @param multipartBo 分片上传对象信息 + * @return OSS对象存储视图对象 + */ + @Override + public SysOssVo completeMultipartUpload(MultipartBo multipartBo) { + String originalName = multipartBo.getOriginalName(); + String suffix = StringUtils.substring(originalName, originalName.lastIndexOf("."), originalName.length()); + List listParts = multipartBo.getPartUploadList().stream() + .map(x -> PartUploadResult.builder() + .partNumber(x.getPartNumber()) + .eTag(x.getETag()) + .build()) + .collect(Collectors.toList()); + OssClient storage = OssFactory.instance(); + UploadResult uploadResult = storage.completeMultipartUpload(multipartBo.getFilename(), multipartBo.getUploadId(), listParts); + // 保存文件信息 + return buildResultEntity(originalName, suffix, storage.getConfigKey(), uploadResult); + } + /** * 桶类型为 private 的URL 修改为临时URL时长为120s * @@ -251,4 +323,5 @@ public class SysOssServiceImpl implements ISysOssService, OssService { } return oss; } + } From abfcb3f84e95638a5d3fa604a755a178c7626bd5 Mon Sep 17 00:00:00 2001 From: AprilWind <2100166581@qq.com> Date: Wed, 24 Apr 2024 11:11:13 +0800 Subject: [PATCH 06/23] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=E5=88=86?= =?UTF-8?q?=E7=89=87=E4=B8=8A=E4=BC=A0=E5=88=9D=E5=A7=8B=E5=8C=96=E9=98=B2?= =?UTF-8?q?=E9=87=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/org/dromara/common/oss/core/OssClient.java | 2 +- .../org/dromara/system/controller/system/SysOssController.java | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/core/OssClient.java b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/core/OssClient.java index 9eae4376d..802f851cb 100644 --- a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/core/OssClient.java +++ b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/core/OssClient.java @@ -426,7 +426,7 @@ public class OssClient { return UploadResult.builder().url(getUrl() + StringUtils.SLASH + key).filename(key).eTag(eTag).build(); } catch (Exception e) { // 捕获异常并抛出自定义异常 - throw new OssException("上传文件失败,请检查配置信息:[" + e.getMessage() + "]"); + throw new OssException("合并文件失败,请检查配置信息:[" + e.getMessage() + "]"); } } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysOssController.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysOssController.java index 269d67d1b..9dac71db9 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysOssController.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysOssController.java @@ -12,6 +12,7 @@ import org.dromara.common.core.domain.R; import org.dromara.common.core.validate.AddGroup; import org.dromara.common.core.validate.EditGroup; import org.dromara.common.core.validate.QueryGroup; +import org.dromara.common.idempotent.annotation.RepeatSubmit; import org.dromara.common.log.annotation.Log; import org.dromara.common.log.enums.BusinessType; import org.dromara.common.mybatis.core.page.PageQuery; @@ -116,6 +117,7 @@ public class SysOssController extends BaseController { * * @param originalName 文件原名 */ + @RepeatSubmit @SaCheckPermission("system:oss:multipart") @PostMapping(value = "/multipart/initiate") public R initiateMultipart(@Size(min = 2, max = 255, message = "文件原名长度必须在2到255之间") From e91fdfc0b135c44d521020d141b652523261d2e6 Mon Sep 17 00:00:00 2001 From: AprilWind <2100166581@qq.com> Date: Wed, 24 Apr 2024 13:34:25 +0800 Subject: [PATCH 07/23] =?UTF-8?q?update=20=E5=A2=9E=E5=8A=A0=E5=88=86?= =?UTF-8?q?=E7=89=87=E7=B1=BB=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/org/dromara/system/domain/bo/MultipartBo.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/MultipartBo.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/MultipartBo.java index 760549959..d32134e48 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/MultipartBo.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/MultipartBo.java @@ -21,6 +21,12 @@ public class MultipartBo implements Serializable { @Serial private static final long serialVersionUID = 1L; + /** + * 分片类型 + */ + @NotBlank(message = "分片类型不能为空", groups = {QueryGroup.class, AddGroup.class, EditGroup.class}) + private String ossStatus; + /** * 文件名 */ From 08307069b024dee3badc9d5eb68aad7e591f23ff Mon Sep 17 00:00:00 2001 From: AprilWind <2100166581@qq.com> Date: Wed, 24 Apr 2024 14:31:19 +0800 Subject: [PATCH 08/23] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=E6=96=AD?= =?UTF-8?q?=E7=82=B9=E7=BB=AD=E4=BC=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/core/constant/GlobalConstants.java | 6 +++++ .../controller/system/SysOssController.java | 20 ++++++---------- .../system/service/ISysOssService.java | 2 +- .../service/impl/SysOssServiceImpl.java | 24 ++++++++++++++----- 4 files changed, 32 insertions(+), 20 deletions(-) diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/GlobalConstants.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/GlobalConstants.java index ae9bc2e62..dbd65fd0a 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/GlobalConstants.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/GlobalConstants.java @@ -36,4 +36,10 @@ public interface GlobalConstants { * 三方认证 redis key */ String SOCIAL_AUTH_CODE_KEY = GLOBAL_REDIS_KEY + "social_auth_codes:"; + + /** + * OSS断点续传 + */ + String OSS_CONTINUATION = GLOBAL_REDIS_KEY + "oss_continuation:"; + } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysOssController.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysOssController.java index 9dac71db9..491ad74c2 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysOssController.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysOssController.java @@ -4,15 +4,12 @@ package org.dromara.system.controller.system; import cn.dev33.satoken.annotation.SaCheckPermission; import cn.hutool.core.util.ObjectUtil; import jakarta.servlet.http.HttpServletResponse; -import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotEmpty; -import jakarta.validation.constraints.Size; import lombok.RequiredArgsConstructor; import org.dromara.common.core.domain.R; import org.dromara.common.core.validate.AddGroup; import org.dromara.common.core.validate.EditGroup; import org.dromara.common.core.validate.QueryGroup; -import org.dromara.common.idempotent.annotation.RepeatSubmit; import org.dromara.common.log.annotation.Log; import org.dromara.common.log.enums.BusinessType; import org.dromara.common.mybatis.core.page.PageQuery; @@ -112,17 +109,14 @@ public class SysOssController extends BaseController { return toAjax(ossService.deleteWithValidByIds(List.of(ossIds), true)); } - /** - * 初始化分片上传任务 - * - * @param originalName 文件原名 - */ - @RepeatSubmit @SaCheckPermission("system:oss:multipart") - @PostMapping(value = "/multipart/initiate") - public R initiateMultipart(@Size(min = 2, max = 255, message = "文件原名长度必须在2到255之间") - @NotBlank(message = "文件原名不能为空") String originalName) { - return R.ok(ossService.initiateMultipart(originalName)); + @PostMapping(value = "/multipart") + public R multipart(@RequestBody MultipartBo multipartBo) { + String ossStatus = multipartBo.getOssStatus(); + + + + return R.ok(ossService.initiateMultipart(multipartBo.getOriginalName(), multipartBo.getMd5Digest())); } /** diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysOssService.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysOssService.java index f7c8adcd7..337e426d5 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysOssService.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysOssService.java @@ -85,7 +85,7 @@ public interface ISysOssService { * @param originalName 文件原名 * @return 分片上传对象信息 */ - MultipartVo initiateMultipart(String originalName); + MultipartVo initiateMultipart(String originalName, String md5Digest); /** * 上传文件的分段(分片上传) diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java index d7dc49e1e..dfd8b5d6e 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java @@ -9,6 +9,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; import org.dromara.common.core.constant.CacheNames; +import org.dromara.common.core.constant.GlobalConstants; import org.dromara.common.core.exception.ServiceException; import org.dromara.common.core.service.OssService; import org.dromara.common.core.utils.MapstructUtils; @@ -23,6 +24,7 @@ import org.dromara.common.oss.entity.PartUploadResult; import org.dromara.common.oss.entity.UploadResult; import org.dromara.common.oss.enumd.AccessPolicyType; import org.dromara.common.oss.factory.OssFactory; +import org.dromara.common.redis.utils.RedisUtils; import org.dromara.system.domain.SysOss; import org.dromara.system.domain.bo.MultipartBo; import org.dromara.system.domain.bo.SysOssBo; @@ -39,6 +41,7 @@ import org.springframework.web.multipart.MultipartFile; import java.io.File; import java.io.IOException; import java.io.InputStream; +import java.time.Duration; import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -248,11 +251,20 @@ public class SysOssServiceImpl implements ISysOssService, OssService { * @return 分片上传对象信息 */ @Override - public MultipartVo initiateMultipart(String originalName) { - String suffix = StringUtils.substring(originalName, originalName.lastIndexOf("."), originalName.length()); - OssClient storage = OssFactory.instance(); - UploadResult uploadResult = storage.initiateMultipart(suffix); - return MapstructUtils.convert(uploadResult, MultipartVo.class); + public MultipartVo initiateMultipart(String originalName, String md5Digest) { + String osskey = GlobalConstants.OSS_CONTINUATION + md5Digest; + MultipartVo multipartVo; + long timeout = RedisUtils.getTimeToLive(osskey); + if ((timeout < 0 ? timeout : timeout / 1000) > 60 * 60 * 2) { + multipartVo = RedisUtils.getCacheObject(osskey); + } else { + String suffix = StringUtils.substring(originalName, originalName.lastIndexOf("."), originalName.length()); + OssClient storage = OssFactory.instance(); + UploadResult uploadResult = storage.initiateMultipart(suffix); + multipartVo = MapstructUtils.convert(uploadResult, MultipartVo.class); + RedisUtils.setCacheObject(osskey, multipartVo, Duration.ofMillis(10800)); + } + return multipartVo; } /** @@ -264,7 +276,7 @@ public class SysOssServiceImpl implements ISysOssService, OssService { @Override public MultipartVo uploadPart(MultipartBo multipartBo) { OssClient storage = OssFactory.instance(); - String privateUrl = storage.uploadPartFutures(multipartBo.getFilename(), multipartBo.getUploadId(), multipartBo.getPartNumber(), multipartBo.getMd5Digest(), 10800); + String privateUrl = storage.uploadPartFutures(multipartBo.getFilename(), multipartBo.getUploadId(), multipartBo.getPartNumber(), multipartBo.getMd5Digest(), 60 * 60 * 72); MultipartVo multipartVo = MapstructUtils.convert(multipartBo, MultipartVo.class); multipartVo.setPrivateUrl(privateUrl); return multipartVo; From 80f95d8684c9a6d8addfd835a718d4c9c5a26aa4 Mon Sep 17 00:00:00 2001 From: AprilWind <2100166581@qq.com> Date: Sun, 28 Apr 2024 09:46:12 +0800 Subject: [PATCH 09/23] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=E5=88=86?= =?UTF-8?q?=E7=89=87=E4=B8=8A=E4=BC=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/system/SysOssController.java | 64 +++++++++---------- 1 file changed, 30 insertions(+), 34 deletions(-) diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysOssController.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysOssController.java index 491ad74c2..30de6d731 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysOssController.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysOssController.java @@ -7,6 +7,8 @@ import jakarta.servlet.http.HttpServletResponse; import jakarta.validation.constraints.NotEmpty; import lombok.RequiredArgsConstructor; import org.dromara.common.core.domain.R; +import org.dromara.common.core.utils.StringUtils; +import org.dromara.common.core.utils.ValidatorUtils; import org.dromara.common.core.validate.AddGroup; import org.dromara.common.core.validate.EditGroup; import org.dromara.common.core.validate.QueryGroup; @@ -17,7 +19,6 @@ import org.dromara.common.mybatis.core.page.TableDataInfo; import org.dromara.common.web.core.BaseController; import org.dromara.system.domain.bo.MultipartBo; import org.dromara.system.domain.bo.SysOssBo; -import org.dromara.system.domain.vo.MultipartVo; import org.dromara.system.domain.vo.SysOssUploadVo; import org.dromara.system.domain.vo.SysOssVo; import org.dromara.system.service.ISysOssService; @@ -109,42 +110,37 @@ public class SysOssController extends BaseController { return toAjax(ossService.deleteWithValidByIds(List.of(ossIds), true)); } + /** + * 分片上传 + */ @SaCheckPermission("system:oss:multipart") @PostMapping(value = "/multipart") - public R multipart(@RequestBody MultipartBo multipartBo) { + public R multipart(@RequestBody MultipartBo multipartBo) { String ossStatus = multipartBo.getOssStatus(); - - - - return R.ok(ossService.initiateMultipart(multipartBo.getOriginalName(), multipartBo.getMd5Digest())); - } - - /** - * 上传分段 - */ - @SaCheckPermission("system:oss:multipart") - @PostMapping(value = "/multipart/upload") - public R uploadPart(@Validated(AddGroup.class) @RequestBody MultipartBo multipartBo) { - return R.ok(ossService.uploadPart(multipartBo)); - } - - /** - * 查询上传分段进度 - */ - @SaCheckPermission("system:oss:multipart") - @PostMapping(value = "/multipart/list") - public R uploadPartList(@Validated(QueryGroup.class) @RequestBody MultipartBo multipartBo) { - return R.ok(ossService.uploadPartList(multipartBo)); - } - - /** - * 合并分段文件 - */ - @SaCheckPermission("system:oss:multipart") - @Log(title = "OSS对象存储-分片", businessType = BusinessType.INSERT) - @PostMapping(value = "/multipart/complete") - public R completeMultipartUpload(@Validated(EditGroup.class) @RequestBody MultipartBo multipartBo) { - return R.ok(ossService.completeMultipartUpload(multipartBo)); + return switch (ossStatus) { + case "initiate" -> { + String originalName = multipartBo.getOriginalName(); + String md5Digest = multipartBo.getMd5Digest(); + if (StringUtils.isNotEmpty(originalName) && StringUtils.isNotEmpty(md5Digest)) { + yield R.ok(ossService.initiateMultipart(originalName, md5Digest)); + } else { + yield R.fail("Original name and MD5 digest cannot be empty"); + } + } + case "upload" -> { + ValidatorUtils.validate(multipartBo, AddGroup.class); + yield R.ok(ossService.uploadPart(multipartBo)); + } + case "list" -> { + ValidatorUtils.validate(multipartBo, QueryGroup.class); + yield R.ok(ossService.uploadPartList(multipartBo)); + } + case "complete" -> { + ValidatorUtils.validate(multipartBo, EditGroup.class); + yield R.ok(ossService.completeMultipartUpload(multipartBo)); + } + default -> R.fail("Invalid OSS status"); + }; } } From 68d8337db4045a88e5cd1840dea117d1d19765d1 Mon Sep 17 00:00:00 2001 From: AprilWind <2100166581@qq.com> Date: Sun, 28 Apr 2024 10:46:10 +0800 Subject: [PATCH 10/23] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=E5=88=86?= =?UTF-8?q?=E7=89=87=E4=B8=8A=E4=BC=A0=E4=BC=A0=E5=8F=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/core/constant/GlobalConstants.java | 5 ++++ .../dromara/system/domain/bo/MultipartBo.java | 18 ++++--------- .../dromara/system/domain/vo/MultipartVo.java | 10 ++++++++ .../service/impl/SysOssServiceImpl.java | 25 ++++++++++++------- 4 files changed, 36 insertions(+), 22 deletions(-) diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/GlobalConstants.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/GlobalConstants.java index dbd65fd0a..c28cddca8 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/GlobalConstants.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/GlobalConstants.java @@ -42,4 +42,9 @@ public interface GlobalConstants { */ String OSS_CONTINUATION = GLOBAL_REDIS_KEY + "oss_continuation:"; + /** + * OSS分片上传 + */ + String OSS_MULTIPART = GLOBAL_REDIS_KEY + "oss_multipart:"; + } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/MultipartBo.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/MultipartBo.java index d32134e48..2bd8ecac0 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/MultipartBo.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/MultipartBo.java @@ -22,16 +22,15 @@ public class MultipartBo implements Serializable { private static final long serialVersionUID = 1L; /** - * 分片类型 + * 分片类型(必传) */ - @NotBlank(message = "分片类型不能为空", groups = {QueryGroup.class, AddGroup.class, EditGroup.class}) private String ossStatus; /** - * 文件名 + * 文件原名(分片初始化的时候使用) */ - @NotBlank(message = "文件名不能为空", groups = {QueryGroup.class, AddGroup.class, EditGroup.class}) - private String filename; + @Size(min = 2, max = 255, message = "文件原名长度必须在2到255之间") + private String originalName; /** * 用于分片上传任务的 Upload ID @@ -48,7 +47,7 @@ public class MultipartBo implements Serializable { private Integer partNumber; /** - * 内容的 MD5 摘要 + * 内容的 MD5 摘要(初始化的时候,需要第一片的md5值用来判断断点续传) */ @Size(max = 255, message = "内容的 MD5 摘要,如果有的话不能超过255", groups = AddGroup.class) private String md5Digest; @@ -66,13 +65,6 @@ public class MultipartBo implements Serializable { @NotNull(message = "分片编号的标记不能为空", groups = QueryGroup.class) private Integer partNumberMarker; - /** - * 原名 - */ - @NotBlank(message = "原名不能为空", groups = EditGroup.class) - @Size(min = 2, max = 255, message = "文件原名长度必须在2到255之间", groups = EditGroup.class) - private String originalName; - /** * 已上传列表(最大长度一万) * 必须是唯一且按照递增顺序排列,严格检查是否漏传 diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/MultipartVo.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/MultipartVo.java index 1dc9f5266..f6b151f0c 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/MultipartVo.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/MultipartVo.java @@ -24,12 +24,22 @@ public class MultipartVo implements Serializable { */ private String filename; + /** + * 文件原名(分片初始化的时候使用) + */ + private String originalName; + /** * 用于分片上传任务的 Upload ID * 在初始化分片上传时获取,并在后续的分片上传和完成上传过程中使用 */ private String uploadId; + /** + * 文件后缀 + */ + private String suffix; + /** * 分片编号(从1开始递增) */ diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java index dfd8b5d6e..2af60a2b5 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java @@ -254,6 +254,7 @@ public class SysOssServiceImpl implements ISysOssService, OssService { public MultipartVo initiateMultipart(String originalName, String md5Digest) { String osskey = GlobalConstants.OSS_CONTINUATION + md5Digest; MultipartVo multipartVo; + // 检查是否存在缓存,如果存在且超时时间在2小时内,则从缓存中获取上传信息 long timeout = RedisUtils.getTimeToLive(osskey); if ((timeout < 0 ? timeout : timeout / 1000) > 60 * 60 * 2) { multipartVo = RedisUtils.getCacheObject(osskey); @@ -262,7 +263,9 @@ public class SysOssServiceImpl implements ISysOssService, OssService { OssClient storage = OssFactory.instance(); UploadResult uploadResult = storage.initiateMultipart(suffix); multipartVo = MapstructUtils.convert(uploadResult, MultipartVo.class); - RedisUtils.setCacheObject(osskey, multipartVo, Duration.ofMillis(10800)); + multipartVo.setSuffix(suffix); + RedisUtils.setCacheObject(osskey, multipartVo, Duration.ofMillis(60 * 60 * 72)); + RedisUtils.setCacheObject(GlobalConstants.OSS_MULTIPART + multipartVo.getUploadId(), multipartVo, Duration.ofMillis(60 * 60 * 72)); } return multipartVo; } @@ -275,10 +278,13 @@ public class SysOssServiceImpl implements ISysOssService, OssService { */ @Override public MultipartVo uploadPart(MultipartBo multipartBo) { + String uploadId = multipartBo.getUploadId(); + Integer partNumber = multipartBo.getPartNumber(); + MultipartVo multipartVo = RedisUtils.getCacheObject(GlobalConstants.OSS_MULTIPART + uploadId); OssClient storage = OssFactory.instance(); - String privateUrl = storage.uploadPartFutures(multipartBo.getFilename(), multipartBo.getUploadId(), multipartBo.getPartNumber(), multipartBo.getMd5Digest(), 60 * 60 * 72); - MultipartVo multipartVo = MapstructUtils.convert(multipartBo, MultipartVo.class); + String privateUrl = storage.uploadPartFutures(multipartVo.getFilename(), uploadId, partNumber, multipartBo.getMd5Digest(), 60 * 60 * 72); multipartVo.setPrivateUrl(privateUrl); + multipartVo.setPartNumber(partNumber); return multipartVo; } @@ -290,9 +296,10 @@ public class SysOssServiceImpl implements ISysOssService, OssService { */ @Override public MultipartVo uploadPartList(MultipartBo multipartBo) { + String uploadId = multipartBo.getUploadId(); + MultipartVo multipartVo = RedisUtils.getCacheObject(GlobalConstants.OSS_MULTIPART + uploadId); OssClient storage = OssFactory.instance(); - List listParts = storage.listParts(multipartBo.getFilename(), multipartBo.getUploadId(), multipartBo.getMaxParts(), multipartBo.getPartNumberMarker()); - MultipartVo multipartVo = MapstructUtils.convert(multipartBo, MultipartVo.class); + List listParts = storage.listParts(multipartVo.getFilename(), uploadId, multipartBo.getMaxParts(), multipartBo.getPartNumberMarker()); multipartVo.setPartUploadList(listParts.stream() .map(x -> new MultipartVo.PartUploadResult(x.getPartNumber(), x.getETag())) .collect(Collectors.toList())); @@ -307,8 +314,8 @@ public class SysOssServiceImpl implements ISysOssService, OssService { */ @Override public SysOssVo completeMultipartUpload(MultipartBo multipartBo) { - String originalName = multipartBo.getOriginalName(); - String suffix = StringUtils.substring(originalName, originalName.lastIndexOf("."), originalName.length()); + String uploadId = multipartBo.getUploadId(); + MultipartVo multipartVo = RedisUtils.getCacheObject(GlobalConstants.OSS_MULTIPART + uploadId); List listParts = multipartBo.getPartUploadList().stream() .map(x -> PartUploadResult.builder() .partNumber(x.getPartNumber()) @@ -316,9 +323,9 @@ public class SysOssServiceImpl implements ISysOssService, OssService { .build()) .collect(Collectors.toList()); OssClient storage = OssFactory.instance(); - UploadResult uploadResult = storage.completeMultipartUpload(multipartBo.getFilename(), multipartBo.getUploadId(), listParts); + UploadResult uploadResult = storage.completeMultipartUpload(multipartVo.getFilename(), uploadId, listParts); // 保存文件信息 - return buildResultEntity(originalName, suffix, storage.getConfigKey(), uploadResult); + return buildResultEntity(multipartVo.getOriginalName(), multipartVo.getSuffix(), storage.getConfigKey(), uploadResult); } /** From 301952357ac179cae3aeebea4912c76e06f4d8f8 Mon Sep 17 00:00:00 2001 From: AprilWind <2100166581@qq.com> Date: Sun, 28 Apr 2024 11:08:53 +0800 Subject: [PATCH 11/23] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=E5=90=88?= =?UTF-8?q?=E5=B9=B6=E5=88=86=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../system/service/impl/SysOssServiceImpl.java | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java index 2af60a2b5..6df7061b4 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java @@ -281,6 +281,9 @@ public class SysOssServiceImpl implements ISysOssService, OssService { String uploadId = multipartBo.getUploadId(); Integer partNumber = multipartBo.getPartNumber(); MultipartVo multipartVo = RedisUtils.getCacheObject(GlobalConstants.OSS_MULTIPART + uploadId); + if (ObjectUtil.isNull(multipartVo)) { + throw new ServiceException("该分片任务不存在!"); + } OssClient storage = OssFactory.instance(); String privateUrl = storage.uploadPartFutures(multipartVo.getFilename(), uploadId, partNumber, multipartBo.getMd5Digest(), 60 * 60 * 72); multipartVo.setPrivateUrl(privateUrl); @@ -298,6 +301,9 @@ public class SysOssServiceImpl implements ISysOssService, OssService { public MultipartVo uploadPartList(MultipartBo multipartBo) { String uploadId = multipartBo.getUploadId(); MultipartVo multipartVo = RedisUtils.getCacheObject(GlobalConstants.OSS_MULTIPART + uploadId); + if (ObjectUtil.isNull(multipartVo)) { + throw new ServiceException("该分片任务不存在!"); + } OssClient storage = OssFactory.instance(); List listParts = storage.listParts(multipartVo.getFilename(), uploadId, multipartBo.getMaxParts(), multipartBo.getPartNumberMarker()); multipartVo.setPartUploadList(listParts.stream() @@ -315,7 +321,11 @@ public class SysOssServiceImpl implements ISysOssService, OssService { @Override public SysOssVo completeMultipartUpload(MultipartBo multipartBo) { String uploadId = multipartBo.getUploadId(); - MultipartVo multipartVo = RedisUtils.getCacheObject(GlobalConstants.OSS_MULTIPART + uploadId); + String uploadIdKey = GlobalConstants.OSS_MULTIPART + uploadId; + MultipartVo multipartVo = RedisUtils.getCacheObject(uploadIdKey); + if (ObjectUtil.isNull(multipartVo)) { + throw new ServiceException("该分片任务不存在!"); + } List listParts = multipartBo.getPartUploadList().stream() .map(x -> PartUploadResult.builder() .partNumber(x.getPartNumber()) @@ -325,7 +335,9 @@ public class SysOssServiceImpl implements ISysOssService, OssService { OssClient storage = OssFactory.instance(); UploadResult uploadResult = storage.completeMultipartUpload(multipartVo.getFilename(), uploadId, listParts); // 保存文件信息 - return buildResultEntity(multipartVo.getOriginalName(), multipartVo.getSuffix(), storage.getConfigKey(), uploadResult); + SysOssVo sysOssVo = buildResultEntity(multipartVo.getOriginalName(), multipartVo.getSuffix(), storage.getConfigKey(), uploadResult); + RedisUtils.deleteObject(uploadIdKey); + return sysOssVo; } /** From 162241741bdab993126fa751d139dc849aa32acc Mon Sep 17 00:00:00 2001 From: AprilWind <2100166581@qq.com> Date: Sun, 28 Apr 2024 11:47:20 +0800 Subject: [PATCH 12/23] =?UTF-8?q?update=20=E4=BF=AE=E5=A4=8DmultipartVo?= =?UTF-8?q?=E8=BD=AC=E6=8D=A2=E5=A4=B1=E8=B4=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/dromara/system/service/impl/SysOssServiceImpl.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java index 6df7061b4..958edd519 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java @@ -253,7 +253,7 @@ public class SysOssServiceImpl implements ISysOssService, OssService { @Override public MultipartVo initiateMultipart(String originalName, String md5Digest) { String osskey = GlobalConstants.OSS_CONTINUATION + md5Digest; - MultipartVo multipartVo; + MultipartVo multipartVo = new MultipartVo(); // 检查是否存在缓存,如果存在且超时时间在2小时内,则从缓存中获取上传信息 long timeout = RedisUtils.getTimeToLive(osskey); if ((timeout < 0 ? timeout : timeout / 1000) > 60 * 60 * 2) { @@ -262,7 +262,8 @@ public class SysOssServiceImpl implements ISysOssService, OssService { String suffix = StringUtils.substring(originalName, originalName.lastIndexOf("."), originalName.length()); OssClient storage = OssFactory.instance(); UploadResult uploadResult = storage.initiateMultipart(suffix); - multipartVo = MapstructUtils.convert(uploadResult, MultipartVo.class); + multipartVo.setFilename(uploadResult.getFilename()); + multipartVo.setUploadId(uploadResult.getUploadId()); multipartVo.setSuffix(suffix); RedisUtils.setCacheObject(osskey, multipartVo, Duration.ofMillis(60 * 60 * 72)); RedisUtils.setCacheObject(GlobalConstants.OSS_MULTIPART + multipartVo.getUploadId(), multipartVo, Duration.ofMillis(60 * 60 * 72)); From 4a931b069be17f845bb1c8daa42a2a6c644dc0f0 Mon Sep 17 00:00:00 2001 From: AprilWind <2100166581@qq.com> Date: Sun, 28 Apr 2024 11:49:05 +0800 Subject: [PATCH 13/23] =?UTF-8?q?update=20=E8=8E=B7=E5=8F=96=E5=8E=9F?= =?UTF-8?q?=E5=A7=8B=E6=96=87=E4=BB=B6=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/org/dromara/system/service/impl/SysOssServiceImpl.java | 1 + 1 file changed, 1 insertion(+) diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java index 958edd519..85f27182d 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java @@ -264,6 +264,7 @@ public class SysOssServiceImpl implements ISysOssService, OssService { UploadResult uploadResult = storage.initiateMultipart(suffix); multipartVo.setFilename(uploadResult.getFilename()); multipartVo.setUploadId(uploadResult.getUploadId()); + multipartVo.setOriginalName(originalName); multipartVo.setSuffix(suffix); RedisUtils.setCacheObject(osskey, multipartVo, Duration.ofMillis(60 * 60 * 72)); RedisUtils.setCacheObject(GlobalConstants.OSS_MULTIPART + multipartVo.getUploadId(), multipartVo, Duration.ofMillis(60 * 60 * 72)); From 251622035f621872014556f6650a2f59c1b1acd1 Mon Sep 17 00:00:00 2001 From: AprilWind <2100166581@qq.com> Date: Sun, 28 Apr 2024 12:40:27 +0800 Subject: [PATCH 14/23] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=E5=88=9D?= =?UTF-8?q?=E5=A7=8B=E5=8C=96=E5=88=86=E7=89=87=E4=B8=8A=E4=BC=A0=E4=BB=BB?= =?UTF-8?q?=E5=8A=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/system/SysOssController.java | 8 +++----- .../system/service/ISysOssService.java | 8 ++++---- .../service/impl/SysOssServiceImpl.java | 20 +++++++++++++------ 3 files changed, 21 insertions(+), 15 deletions(-) diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysOssController.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysOssController.java index 30de6d731..f6c87d968 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysOssController.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysOssController.java @@ -119,10 +119,8 @@ public class SysOssController extends BaseController { String ossStatus = multipartBo.getOssStatus(); return switch (ossStatus) { case "initiate" -> { - String originalName = multipartBo.getOriginalName(); - String md5Digest = multipartBo.getMd5Digest(); - if (StringUtils.isNotEmpty(originalName) && StringUtils.isNotEmpty(md5Digest)) { - yield R.ok(ossService.initiateMultipart(originalName, md5Digest)); + if (StringUtils.isNotEmpty(multipartBo.getOriginalName()) && StringUtils.isNotEmpty(multipartBo.getMd5Digest())) { + yield R.ok(ossService.initiateMultipart(multipartBo)); } else { yield R.fail("Original name and MD5 digest cannot be empty"); } @@ -131,7 +129,7 @@ public class SysOssController extends BaseController { ValidatorUtils.validate(multipartBo, AddGroup.class); yield R.ok(ossService.uploadPart(multipartBo)); } - case "list" -> { + case "query" -> { ValidatorUtils.validate(multipartBo, QueryGroup.class); yield R.ok(ossService.uploadPartList(multipartBo)); } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysOssService.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysOssService.java index 337e426d5..4a0a5e3a0 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysOssService.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysOssService.java @@ -82,16 +82,16 @@ public interface ISysOssService { /** * 初始化分片上传任务 * - * @param originalName 文件原名 + * @param multipartBo 初始化分片的参数对象 * @return 分片上传对象信息 */ - MultipartVo initiateMultipart(String originalName, String md5Digest); + MultipartVo initiateMultipart(MultipartBo multipartBo); /** * 上传文件的分段(分片上传) * - * @param multipartBo SysOssMultipartBo 分段上传的参数对象 - * @return SysOssMultipartVo 分片上传成功后的对象信息 + * @param multipartBo 分段上传的参数对象 + * @return 分片上传成功后的对象信息 */ MultipartVo uploadPart(MultipartBo multipartBo); diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java index 85f27182d..4e81e6f19 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java @@ -247,20 +247,28 @@ public class SysOssServiceImpl implements ISysOssService, OssService { /** * 初始化分片上传任务 * - * @param originalName 文件原名 + * @param multipartBo 初始化分片的参数对象 * @return 分片上传对象信息 */ @Override - public MultipartVo initiateMultipart(String originalName, String md5Digest) { - String osskey = GlobalConstants.OSS_CONTINUATION + md5Digest; + public MultipartVo initiateMultipart(MultipartBo multipartBo) { + OssClient storage = OssFactory.instance(); + String osskey = GlobalConstants.OSS_CONTINUATION + multipartBo.getMd5Digest(); MultipartVo multipartVo = new MultipartVo(); + // 检查是否存在缓存,如果存在且超时时间在2小时内,则从缓存中获取上传信息 long timeout = RedisUtils.getTimeToLive(osskey); if ((timeout < 0 ? timeout : timeout / 1000) > 60 * 60 * 2) { multipartVo = RedisUtils.getCacheObject(osskey); + + // 获取上传分段进度 + List listParts = storage.listParts(multipartVo.getFilename(), multipartVo.getUploadId(), null, null); + multipartVo.setPartUploadList(listParts.stream() + .map(x -> new MultipartVo.PartUploadResult(x.getPartNumber(), x.getETag())) + .collect(Collectors.toList())); } else { + String originalName = multipartBo.getOriginalName(); String suffix = StringUtils.substring(originalName, originalName.lastIndexOf("."), originalName.length()); - OssClient storage = OssFactory.instance(); UploadResult uploadResult = storage.initiateMultipart(suffix); multipartVo.setFilename(uploadResult.getFilename()); multipartVo.setUploadId(uploadResult.getUploadId()); @@ -275,8 +283,8 @@ public class SysOssServiceImpl implements ISysOssService, OssService { /** * 上传文件的分段(分片上传) * - * @param multipartBo MultipartBo 分段上传的参数对象 - * @return MultipartVo 分片上传成功后的对象信息 + * @param multipartBo 分段上传的参数对象 + * @return 分片上传成功后的对象信息 */ @Override public MultipartVo uploadPart(MultipartBo multipartBo) { From 12136c3926e409364faa3ad401ed83e424df25fa Mon Sep 17 00:00:00 2001 From: AprilWind <2100166581@qq.com> Date: Sun, 28 Apr 2024 12:49:27 +0800 Subject: [PATCH 15/23] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=E8=B6=85?= =?UTF-8?q?=E6=97=B6=E6=97=B6=E9=97=B4=E5=88=A4=E6=96=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/dromara/system/service/impl/SysOssServiceImpl.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java index 4e81e6f19..c382a065c 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java @@ -257,8 +257,7 @@ public class SysOssServiceImpl implements ISysOssService, OssService { MultipartVo multipartVo = new MultipartVo(); // 检查是否存在缓存,如果存在且超时时间在2小时内,则从缓存中获取上传信息 - long timeout = RedisUtils.getTimeToLive(osskey); - if ((timeout < 0 ? timeout : timeout / 1000) > 60 * 60 * 2) { + if (RedisUtils.getTimeToLive(osskey) > 60 * 60 * 2 * 1000) { multipartVo = RedisUtils.getCacheObject(osskey); // 获取上传分段进度 From 50636e3fb3b6ecc201fa19a187a0f75d221bd661 Mon Sep 17 00:00:00 2001 From: AprilWind <2100166581@qq.com> Date: Sun, 28 Apr 2024 13:03:05 +0800 Subject: [PATCH 16/23] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=E5=88=86?= =?UTF-8?q?=E7=89=87=E4=B8=8A=E4=BC=A0=E7=B1=BB=E5=9E=8B=E5=88=A4=E6=96=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/dromara/system/controller/system/SysOssController.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysOssController.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysOssController.java index f6c87d968..67f82b6d3 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysOssController.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysOssController.java @@ -116,8 +116,7 @@ public class SysOssController extends BaseController { @SaCheckPermission("system:oss:multipart") @PostMapping(value = "/multipart") public R multipart(@RequestBody MultipartBo multipartBo) { - String ossStatus = multipartBo.getOssStatus(); - return switch (ossStatus) { + return switch (multipartBo.getOssStatus()) { case "initiate" -> { if (StringUtils.isNotEmpty(multipartBo.getOriginalName()) && StringUtils.isNotEmpty(multipartBo.getMd5Digest())) { yield R.ok(ossService.initiateMultipart(multipartBo)); From f25ebd71bbc5302b8a303c91201fc4e16a2017c9 Mon Sep 17 00:00:00 2001 From: AprilWind <2100166581@qq.com> Date: Wed, 8 May 2024 13:45:05 +0800 Subject: [PATCH 17/23] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=E5=88=86?= =?UTF-8?q?=E7=89=87=E4=B8=8A=E4=BC=A0=E7=BC=96=E5=8F=B7=E6=9C=80=E5=A4=A7?= =?UTF-8?q?=E5=80=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/org/dromara/system/domain/bo/MultipartBo.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/MultipartBo.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/MultipartBo.java index 2bd8ecac0..d890ecb14 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/MultipartBo.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/MultipartBo.java @@ -7,6 +7,7 @@ import lombok.Data; import org.dromara.common.core.validate.AddGroup; import org.dromara.common.core.validate.EditGroup; import org.dromara.common.core.validate.QueryGroup; +import org.hibernate.validator.constraints.Range; import java.io.Serial; import java.io.Serializable; @@ -43,7 +44,7 @@ public class MultipartBo implements Serializable { * 分片编号(从1开始递增) */ @NotNull(message = "分片编号不能为空", groups = AddGroup.class) - @Size(min = 1, max = 10000, message = "分片编号必须介于1和10,000之间", groups = AddGroup.class) + @Range(min = 1, max = 10000, message = "分片编号必须介于1和10,000之间", groups = AddGroup.class) private Integer partNumber; /** @@ -83,7 +84,7 @@ public class MultipartBo implements Serializable { * 分片编号(从1开始递增) */ @NotNull(message = "分片编号不能为空", groups = EditGroup.class) - @Size(min = 1, max = 10000, message = "分片编号必须介于1和10,000之间", groups = EditGroup.class) + @Range(min = 1, max = 10000, message = "分片编号必须介于1和10,000之间", groups = EditGroup.class) private Integer partNumber; /** From f76893ff9bf24abdb82e558a2a7056388b21a719 Mon Sep 17 00:00:00 2001 From: AprilWind <2100166581@qq.com> Date: Thu, 9 May 2024 08:35:15 +0800 Subject: [PATCH 18/23] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=E5=88=86?= =?UTF-8?q?=E7=89=87=E4=B8=8A=E4=BC=A0=E5=86=85=E9=83=A8=E7=B1=BB=E6=A0=A1?= =?UTF-8?q?=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/org/dromara/system/domain/bo/MultipartBo.java | 5 +++++ .../main/java/org/dromara/system/domain/vo/MultipartVo.java | 3 +++ 2 files changed, 8 insertions(+) diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/MultipartBo.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/MultipartBo.java index d890ecb14..37249c714 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/MultipartBo.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/MultipartBo.java @@ -1,5 +1,6 @@ package org.dromara.system.domain.bo; +import jakarta.validation.Valid; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Size; @@ -14,6 +15,8 @@ import java.io.Serializable; import java.util.List; /** + * 分片上传 + * * @author AprilWind */ @Data @@ -49,6 +52,7 @@ public class MultipartBo implements Serializable { /** * 内容的 MD5 摘要(初始化的时候,需要第一片的md5值用来判断断点续传) + * */ @Size(max = 255, message = "内容的 MD5 摘要,如果有的话不能超过255", groups = AddGroup.class) private String md5Digest; @@ -70,6 +74,7 @@ public class MultipartBo implements Serializable { * 已上传列表(最大长度一万) * 必须是唯一且按照递增顺序排列,严格检查是否漏传 */ + @Valid @NotNull(message = "已上传列表不能为空") @Size(min = 2, max = 10000, message = "已上传列表长度必须在2到10000之间", groups = EditGroup.class) private List partUploadList; diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/MultipartVo.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/MultipartVo.java index f6b151f0c..d7609ae6b 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/MultipartVo.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/MultipartVo.java @@ -10,6 +10,8 @@ import java.io.Serializable; import java.util.List; /** + * 分片上传 + * * @author AprilWind */ @Data @@ -54,6 +56,7 @@ public class MultipartVo implements Serializable { /** * 已上传列表(最大长度一千) * 必须是唯一且按照递增顺序排列,严格检查是否漏传 + * ‘initiate’初始化状态时如果返回值,说明是断点续传,如果前端分片大于一千,需要请求‘query’获取 */ private List partUploadList; From 38be1c9ac2e49a7e54082f60cfa670aa38c7c1fe Mon Sep 17 00:00:00 2001 From: AprilWind <2100166581@qq.com> Date: Thu, 9 May 2024 08:51:47 +0800 Subject: [PATCH 19/23] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=E5=88=86?= =?UTF-8?q?=E7=89=87=E4=B8=8A=E4=BC=A0=E6=96=AD=E7=82=B9=E7=BB=AD=E4=BC=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/org/dromara/system/domain/bo/MultipartBo.java | 8 ++++++-- .../dromara/system/service/impl/SysOssServiceImpl.java | 4 +++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/MultipartBo.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/MultipartBo.java index 37249c714..904ccd6c5 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/MultipartBo.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/MultipartBo.java @@ -51,9 +51,11 @@ public class MultipartBo implements Serializable { private Integer partNumber; /** - * 内容的 MD5 摘要(初始化的时候,需要第一片的md5值用来判断断点续传) - * + * 内容的 MD5 摘要 + * (initiate初始化、合并complete的时候,需要第一片的md5值用来判断断点续传) + * upload状态时,非必需(如果有值会校验) */ + @NotBlank(message = "第一片的md5值不能为空", groups = EditGroup.class) @Size(max = 255, message = "内容的 MD5 摘要,如果有的话不能超过255", groups = AddGroup.class) private String md5Digest; @@ -62,12 +64,14 @@ public class MultipartBo implements Serializable { * 最多分片一万,一次性返回会造成前端性能问题,需要前端多次校验 */ @NotNull(message = "最大返回的分片数不能为空", groups = QueryGroup.class) + @Range(max = 1000, message = "最大返回的分片数不能超过1000", groups = EditGroup.class) private Integer maxParts; /** * 分片编号的标记,用于分页查询(默认为0,表示从第一个分片开始查询) */ @NotNull(message = "分片编号的标记不能为空", groups = QueryGroup.class) + @Range(min = 0, max = 10000, message = "分片编号的标记长度必须在0到10000之间", groups = EditGroup.class) private Integer partNumberMarker; /** diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java index c382a065c..3892bba65 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java @@ -25,6 +25,7 @@ import org.dromara.common.oss.entity.UploadResult; import org.dromara.common.oss.enumd.AccessPolicyType; import org.dromara.common.oss.factory.OssFactory; import org.dromara.common.redis.utils.RedisUtils; +import org.dromara.common.satoken.utils.LoginHelper; import org.dromara.system.domain.SysOss; import org.dromara.system.domain.bo.MultipartBo; import org.dromara.system.domain.bo.SysOssBo; @@ -253,7 +254,7 @@ public class SysOssServiceImpl implements ISysOssService, OssService { @Override public MultipartVo initiateMultipart(MultipartBo multipartBo) { OssClient storage = OssFactory.instance(); - String osskey = GlobalConstants.OSS_CONTINUATION + multipartBo.getMd5Digest(); + String osskey = GlobalConstants.OSS_CONTINUATION + LoginHelper.getUserId() + multipartBo.getMd5Digest(); MultipartVo multipartVo = new MultipartVo(); // 检查是否存在缓存,如果存在且超时时间在2小时内,则从缓存中获取上传信息 @@ -346,6 +347,7 @@ public class SysOssServiceImpl implements ISysOssService, OssService { // 保存文件信息 SysOssVo sysOssVo = buildResultEntity(multipartVo.getOriginalName(), multipartVo.getSuffix(), storage.getConfigKey(), uploadResult); RedisUtils.deleteObject(uploadIdKey); + RedisUtils.deleteObject(GlobalConstants.OSS_CONTINUATION + LoginHelper.getUserId() + multipartBo.getMd5Digest()); return sysOssVo; } From f7583b8e56c62f27f36c6c680792e7e28fa782f4 Mon Sep 17 00:00:00 2001 From: AprilWind <2100166581@qq.com> Date: Thu, 9 May 2024 09:18:21 +0800 Subject: [PATCH 20/23] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=E5=88=86?= =?UTF-8?q?=E7=89=87=E4=B8=8A=E4=BC=A0=E5=88=86=E7=BB=84=E6=A0=A1=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/org/dromara/system/domain/bo/MultipartBo.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/MultipartBo.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/MultipartBo.java index 904ccd6c5..13087b9b5 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/MultipartBo.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/MultipartBo.java @@ -64,14 +64,14 @@ public class MultipartBo implements Serializable { * 最多分片一万,一次性返回会造成前端性能问题,需要前端多次校验 */ @NotNull(message = "最大返回的分片数不能为空", groups = QueryGroup.class) - @Range(max = 1000, message = "最大返回的分片数不能超过1000", groups = EditGroup.class) + @Range(max = 1000, message = "最大返回的分片数不能超过1000", groups = QueryGroup.class) private Integer maxParts; /** * 分片编号的标记,用于分页查询(默认为0,表示从第一个分片开始查询) */ @NotNull(message = "分片编号的标记不能为空", groups = QueryGroup.class) - @Range(min = 0, max = 10000, message = "分片编号的标记长度必须在0到10000之间", groups = EditGroup.class) + @Range(min = 0, max = 10000, message = "分片编号的标记长度必须在0到10000之间", groups = QueryGroup.class) private Integer partNumberMarker; /** From 8792129aeda630a980ec95026dfee7546484001a Mon Sep 17 00:00:00 2001 From: AprilWind <2100166581@qq.com> Date: Thu, 9 May 2024 09:19:21 +0800 Subject: [PATCH 21/23] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=E5=88=86?= =?UTF-8?q?=E7=89=87=E4=B8=8A=E4=BC=A0=E5=88=86=E7=BB=84=E6=A0=A1=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/org/dromara/system/domain/bo/MultipartBo.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/MultipartBo.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/MultipartBo.java index 13087b9b5..1ba06a940 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/MultipartBo.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/MultipartBo.java @@ -56,7 +56,7 @@ public class MultipartBo implements Serializable { * upload状态时,非必需(如果有值会校验) */ @NotBlank(message = "第一片的md5值不能为空", groups = EditGroup.class) - @Size(max = 255, message = "内容的 MD5 摘要,如果有的话不能超过255", groups = AddGroup.class) + @Size(max = 255, message = "内容的 MD5 摘要,如果有的话不能超过255", groups = {AddGroup.class, EditGroup.class}) private String md5Digest; /** From 1e559b71b33dbbe03b3e31a61e28673a71e0db50 Mon Sep 17 00:00:00 2001 From: AprilWind <2100166581@qq.com> Date: Thu, 9 May 2024 10:15:31 +0800 Subject: [PATCH 22/23] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=E5=88=86?= =?UTF-8?q?=E7=89=87=E4=B8=8A=E4=BC=A0=E9=94=AE=E5=80=BC=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/org/dromara/system/domain/bo/MultipartBo.java | 6 ++---- .../main/java/org/dromara/system/domain/vo/MultipartVo.java | 5 +++++ .../org/dromara/system/service/impl/SysOssServiceImpl.java | 2 +- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/MultipartBo.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/MultipartBo.java index 1ba06a940..400cdf0de 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/MultipartBo.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/MultipartBo.java @@ -52,11 +52,9 @@ public class MultipartBo implements Serializable { /** * 内容的 MD5 摘要 - * (initiate初始化、合并complete的时候,需要第一片的md5值用来判断断点续传) - * upload状态时,非必需(如果有值会校验) + * initiate初始化需要第一片的md5值用来判断断点续传,upload状态时,非必需(如果有值会校验) */ - @NotBlank(message = "第一片的md5值不能为空", groups = EditGroup.class) - @Size(max = 255, message = "内容的 MD5 摘要,如果有的话不能超过255", groups = {AddGroup.class, EditGroup.class}) + @Size(max = 255, message = "内容的 MD5 摘要,如果有的话不能超过255", groups = AddGroup.class) private String md5Digest; /** diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/MultipartVo.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/MultipartVo.java index d7609ae6b..8889f4d76 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/MultipartVo.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/MultipartVo.java @@ -31,6 +31,11 @@ public class MultipartVo implements Serializable { */ private String originalName; + /** + * 分片第一片的md5值 + */ + private String md5Digest; + /** * 用于分片上传任务的 Upload ID * 在初始化分片上传时获取,并在后续的分片上传和完成上传过程中使用 diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java index 3892bba65..c59592ee8 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java @@ -347,7 +347,7 @@ public class SysOssServiceImpl implements ISysOssService, OssService { // 保存文件信息 SysOssVo sysOssVo = buildResultEntity(multipartVo.getOriginalName(), multipartVo.getSuffix(), storage.getConfigKey(), uploadResult); RedisUtils.deleteObject(uploadIdKey); - RedisUtils.deleteObject(GlobalConstants.OSS_CONTINUATION + LoginHelper.getUserId() + multipartBo.getMd5Digest()); + RedisUtils.deleteObject(GlobalConstants.OSS_CONTINUATION + LoginHelper.getUserId() + multipartVo.getMd5Digest()); return sysOssVo; } From a873783aa5fab1da5327d07c554945eb07cefcd6 Mon Sep 17 00:00:00 2001 From: AprilWind <2100166581@qq.com> Date: Thu, 9 May 2024 17:59:29 +0800 Subject: [PATCH 23/23] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=E5=88=86?= =?UTF-8?q?=E7=89=87=E4=B8=8A=E4=BC=A0=E9=94=AE=E5=80=BC=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/dromara/system/service/impl/SysOssServiceImpl.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java index c59592ee8..a5b543ea7 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java @@ -254,7 +254,8 @@ public class SysOssServiceImpl implements ISysOssService, OssService { @Override public MultipartVo initiateMultipart(MultipartBo multipartBo) { OssClient storage = OssFactory.instance(); - String osskey = GlobalConstants.OSS_CONTINUATION + LoginHelper.getUserId() + multipartBo.getMd5Digest(); + String md5Digest = multipartBo.getMd5Digest(); + String osskey = GlobalConstants.OSS_CONTINUATION + LoginHelper.getUserId() + md5Digest; MultipartVo multipartVo = new MultipartVo(); // 检查是否存在缓存,如果存在且超时时间在2小时内,则从缓存中获取上传信息 @@ -272,6 +273,7 @@ public class SysOssServiceImpl implements ISysOssService, OssService { UploadResult uploadResult = storage.initiateMultipart(suffix); multipartVo.setFilename(uploadResult.getFilename()); multipartVo.setUploadId(uploadResult.getUploadId()); + multipartVo.setMd5Digest(md5Digest); multipartVo.setOriginalName(originalName); multipartVo.setSuffix(suffix); RedisUtils.setCacheObject(osskey, multipartVo, Duration.ofMillis(60 * 60 * 72));