thUserMetadata;
+
/**
* 附加属性字典
*/
@@ -98,7 +122,7 @@ public class FileInfo implements Serializable {
/**
* 文件的访问控制列表,一般情况下只有对象存储支持该功能,支持 String 或对应存储平台的 ACL 对象
*
- * //方式一,通过字符串设置通用的 ACL 详情:{@link cn.xuyanwu.spring.file.storage.constant.Constant.ACL }
+ * //方式一,通过字符串设置通用的 ACL 详情:{@link Constant.ACL }
* setFileAcl(ACL.PUBLIC_READ);
* //方式二,针对指定存储平台设置更复杂的权限控制,以华为云 OBS 为例
* AccessControlList acl = new AccessControlList();
@@ -118,7 +142,7 @@ public class FileInfo implements Serializable {
/**
* 缩略图的访问控制列表,一般情况下只有对象存储支持该功能
- * 详情见{@link cn.xuyanwu.spring.file.storage.FileInfo#setFileAcl}
+ * 详情见{@link FileInfo#setFileAcl}
*/
private Object thFileAcl;
diff --git a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/FileStorageProperties.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/FileStorageProperties.java
similarity index 95%
rename from file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/FileStorageProperties.java
rename to x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/FileStorageProperties.java
index fd560a9c..f819c67c 100644
--- a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/FileStorageProperties.java
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/FileStorageProperties.java
@@ -1,9 +1,10 @@
-package cn.xuyanwu.spring.file.storage;
+package org.dromara.x.file.storage.core;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
+import org.dromara.x.file.storage.core.constant.Constant;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
@@ -25,6 +26,14 @@ public class FileStorageProperties {
* 缩略图后缀,例如【.min.jpg】【.png】
*/
private String thumbnailSuffix = ".min.jpg";
+ /**
+ * 上传时不支持元数据时抛出异常
+ */
+ private Boolean uploadNotSupportMetadataThrowException = true;
+ /**
+ * 上传时不支持 ACL 时抛出异常
+ */
+ private Boolean uploadNotSupportAclThrowException = true;
/**
* 本地存储
*/
@@ -161,7 +170,7 @@ public static class HuaweiObsConfig extends BaseConfig {
*/
private String basePath = "";
/**
- * 默认的 ACL,详情 {@link cn.xuyanwu.spring.file.storage.constant.Constant.HuaweiObsACL}
+ * 默认的 ACL,详情 {@link Constant.HuaweiObsACL}
*/
private String defaultAcl;
/**
@@ -197,7 +206,7 @@ public static class AliyunOssConfig extends BaseConfig {
*/
private String basePath = "";
/**
- * 默认的 ACL,详情 {@link cn.xuyanwu.spring.file.storage.constant.Constant.AliyunOssACL}
+ * 默认的 ACL,详情 {@link Constant.AliyunOssACL}
*/
private String defaultAcl;
/**
@@ -256,7 +265,7 @@ public static class TencentCosConfig extends BaseConfig {
*/
private String basePath = "";
/**
- * 默认的 ACL,详情 {@link cn.xuyanwu.spring.file.storage.constant.Constant.TencentCosACL}
+ * 默认的 ACL,详情 {@link Constant.TencentCosACL}
*/
private String defaultAcl;
/**
@@ -292,7 +301,7 @@ public static class BaiduBosConfig extends BaseConfig {
*/
private String basePath = "";
/**
- * 默认的 ACL,详情 {@link cn.xuyanwu.spring.file.storage.constant.Constant.BaiduBosACL}
+ * 默认的 ACL,详情 {@link Constant.BaiduBosACL}
*/
private String defaultAcl;
/**
@@ -376,7 +385,7 @@ public static class AmazonS3Config extends BaseConfig {
*/
private String basePath = "";
/**
- * 默认的 ACL,详情 {@link cn.xuyanwu.spring.file.storage.constant.Constant.AwsS3ACL}
+ * 默认的 ACL,详情 {@link Constant.AwsS3ACL}
*/
private String defaultAcl;
/**
@@ -572,7 +581,7 @@ public static class GoogleCloudStorageConfig extends BaseConfig {
*/
private String basePath = "";
/**
- * 默认的 ACL,详情 {@link cn.xuyanwu.spring.file.storage.constant.Constant.GoogleCloudStorageACL}
+ * 默认的 ACL,详情 {@link Constant.GoogleCloudStorageACL}
*/
private String defaultAcl;
/**
diff --git a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/FileStorageService.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/FileStorageService.java
similarity index 84%
rename from file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/FileStorageService.java
rename to x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/FileStorageService.java
index 9e6b40d3..e1f1d42c 100644
--- a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/FileStorageService.java
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/FileStorageService.java
@@ -1,20 +1,22 @@
-package cn.xuyanwu.spring.file.storage;
+package org.dromara.x.file.storage.core;
import cn.hutool.core.io.file.FileNameUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
-import cn.xuyanwu.spring.file.storage.aspect.*;
-import cn.xuyanwu.spring.file.storage.exception.FileStorageRuntimeException;
-import cn.xuyanwu.spring.file.storage.file.FileWrapper;
-import cn.xuyanwu.spring.file.storage.file.FileWrapperAdapter;
-import cn.xuyanwu.spring.file.storage.platform.FileStorage;
-import cn.xuyanwu.spring.file.storage.recorder.FileRecorder;
-import cn.xuyanwu.spring.file.storage.tika.ContentTypeDetect;
-import cn.xuyanwu.spring.file.storage.util.Tools;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
+import org.dromara.x.file.storage.core.aspect.*;
+import org.dromara.x.file.storage.core.exception.FileStorageRuntimeException;
+import org.dromara.x.file.storage.core.file.FileWrapper;
+import org.dromara.x.file.storage.core.file.FileWrapperAdapter;
+import org.dromara.x.file.storage.core.file.HttpServletRequestFileWrapper;
+import org.dromara.x.file.storage.core.file.MultipartFormDataReader;
+import org.dromara.x.file.storage.core.platform.FileStorage;
+import org.dromara.x.file.storage.core.recorder.FileRecorder;
+import org.dromara.x.file.storage.core.tika.ContentTypeDetect;
+import org.dromara.x.file.storage.core.util.Tools;
import java.io.IOException;
import java.util.Date;
@@ -35,6 +37,8 @@ public class FileStorageService {
private CopyOnWriteArrayList fileStorageList;
private String defaultPlatform;
private String thumbnailSuffix;
+ private Boolean uploadNotSupportMetadataThrowException;
+ private Boolean uploadNotSupportAclThrowException;
private CopyOnWriteArrayList aspectList;
private CopyOnWriteArrayList fileWrapperAdapterList;
private ContentTypeDetect contentTypeDetect;
@@ -92,6 +96,10 @@ public FileInfo upload(UploadPretreatment pre) {
fileInfo.setObjectType(pre.getObjectType());
fileInfo.setPath(pre.getPath());
fileInfo.setPlatform(pre.getPlatform());
+ fileInfo.setMetadata(pre.getMetadata());
+ fileInfo.setUserMetadata(pre.getUserMetadata());
+ fileInfo.setThMetadata(pre.getThMetadata());
+ fileInfo.setThUserMetadata(pre.getThUserMetadata());
fileInfo.setAttr(pre.getAttr());
fileInfo.setFileAcl(pre.getFileAcl());
fileInfo.setThFileAcl(pre.getThFileAcl());
@@ -264,7 +272,7 @@ public String generateThPresignedUrl(FileInfo fileInfo,Date expiration) {
}
/**
- * 是否支持对文件生成可以签名访问的 URL
+ * 是否支持对文件的访问控制列表
*/
public boolean isSupportAcl(String platform) {
FileStorage storage = self.getFileStorageVerify(platform);
@@ -272,7 +280,7 @@ public boolean isSupportAcl(String platform) {
}
/**
- * 是否支持对文件生成可以签名访问的 URL
+ * 是否支持对文件的访问控制列表
*/
public boolean isSupportAcl(FileStorage fileStorage) {
if (fileStorage == null) return false;
@@ -281,7 +289,7 @@ public boolean isSupportAcl(FileStorage fileStorage) {
/**
* 设置文件的访问控制列表,一般情况下只有对象存储支持该功能
- * 详情见{@link cn.xuyanwu.spring.file.storage.FileInfo#setFileAcl}
+ * 详情见{@link FileInfo#setFileAcl}
*/
public boolean setFileAcl(FileInfo fileInfo,Object acl) {
if (fileInfo == null) return false;
@@ -292,7 +300,7 @@ public boolean setFileAcl(FileInfo fileInfo,Object acl) {
/**
* 设置缩略图文件的访问控制列表,一般情况下只有对象存储支持该功能
- * 详情见{@link cn.xuyanwu.spring.file.storage.FileInfo#setFileAcl}
+ * 详情见{@link FileInfo#setFileAcl}
*/
public boolean setThFileAcl(FileInfo fileInfo,Object acl) {
if (fileInfo == null) return false;
@@ -301,6 +309,22 @@ public boolean setThFileAcl(FileInfo fileInfo,Object acl) {
).next(fileInfo,acl,self.getFileStorageVerify(fileInfo));
}
+ /**
+ * 是否支持 Metadata
+ */
+ public boolean isSupportMetadata(String platform) {
+ FileStorage storage = self.getFileStorageVerify(platform);
+ return self.isSupportMetadata(storage);
+ }
+
+ /**
+ * 是否支持 Metadata
+ */
+ public boolean isSupportMetadata(FileStorage fileStorage) {
+ if (fileStorage == null) return false;
+ return new IsSupportMetadataAspectChain(aspectList,FileStorage::isSupportMetadata).next(fileStorage);
+ }
+
/**
* 创建上传预处理器
*/
@@ -309,6 +333,8 @@ public UploadPretreatment of() {
pre.setFileStorageService(self);
pre.setPlatform(defaultPlatform);
pre.setThumbnailSuffix(thumbnailSuffix);
+ pre.setNotSupportMetadataThrowException(uploadNotSupportMetadataThrowException);
+ pre.setNotSupportAclThrowException(uploadNotSupportAclThrowException);
return pre;
}
@@ -339,7 +365,7 @@ public UploadPretreatment of(Object source,String name) {
* @param contentType 文件的 MIME 类型
*/
public UploadPretreatment of(Object source,String name,String contentType) {
- return self.of().setFileWrapper(self.wrapper(source,name,contentType));
+ return self.of(source,name,contentType,null);
}
/**
@@ -351,7 +377,17 @@ public UploadPretreatment of(Object source,String name,String contentType) {
* @param size 文件大小
*/
public UploadPretreatment of(Object source,String name,String contentType,Long size) {
- return self.of().setFileWrapper(self.wrapper(source,name,contentType,size));
+ FileWrapper wrapper = self.wrapper(source,name,contentType,size);
+ UploadPretreatment up = self.of().setFileWrapper(wrapper);
+ //这里针对 HttpServletRequestFileWrapper 特殊处理,加载读取到的缩略图文件
+ if (wrapper instanceof HttpServletRequestFileWrapper) {
+ MultipartFormDataReader.MultipartFormData data = ((HttpServletRequestFileWrapper) wrapper).getMultipartFormData();
+ if (data.getThFileBytes() != null) {
+ FileWrapper thWrapper = self.wrapper(data.getThFileBytes(),data.getThFileOriginalFilename(),data.getThFileContentType());
+ up.thumbnailOf(thWrapper);
+ }
+ }
+ return up;
}
/**
diff --git a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/FileStorageServiceBuilder.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/FileStorageServiceBuilder.java
similarity index 91%
rename from file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/FileStorageServiceBuilder.java
rename to x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/FileStorageServiceBuilder.java
index d43da4c3..44b57d41 100644
--- a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/FileStorageServiceBuilder.java
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/FileStorageServiceBuilder.java
@@ -1,20 +1,8 @@
-package cn.xuyanwu.spring.file.storage;
+package org.dromara.x.file.storage.core;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.extra.ftp.Ftp;
import cn.hutool.extra.ssh.Sftp;
-import cn.xuyanwu.spring.file.storage.FileStorageProperties.*;
-import cn.xuyanwu.spring.file.storage.aspect.FileStorageAspect;
-import cn.xuyanwu.spring.file.storage.exception.FileStorageRuntimeException;
-import cn.xuyanwu.spring.file.storage.file.*;
-import cn.xuyanwu.spring.file.storage.platform.*;
-import cn.xuyanwu.spring.file.storage.platform.QiniuKodoFileStorageClientFactory.QiniuKodoClient;
-import cn.xuyanwu.spring.file.storage.recorder.DefaultFileRecorder;
-import cn.xuyanwu.spring.file.storage.recorder.FileRecorder;
-import cn.xuyanwu.spring.file.storage.tika.ContentTypeDetect;
-import cn.xuyanwu.spring.file.storage.tika.DefaultTikaFactory;
-import cn.xuyanwu.spring.file.storage.tika.TikaContentTypeDetect;
-import cn.xuyanwu.spring.file.storage.tika.TikaFactory;
import com.aliyun.oss.OSS;
import com.amazonaws.services.s3.AmazonS3;
import com.baidubce.services.bos.BosClient;
@@ -28,6 +16,19 @@
import lombok.Setter;
import lombok.experimental.Accessors;
import lombok.extern.slf4j.Slf4j;
+import org.dromara.x.file.storage.core.FileStorageProperties.*;
+import org.dromara.x.file.storage.core.aspect.FileStorageAspect;
+import org.dromara.x.file.storage.core.exception.FileStorageRuntimeException;
+import org.dromara.x.file.storage.core.file.*;
+import org.dromara.x.file.storage.core.platform.*;
+import org.dromara.x.file.storage.core.platform.QiniuKodoFileStorageClientFactory.QiniuKodoClient;
+import org.dromara.x.file.storage.core.recorder.DefaultFileRecorder;
+import org.dromara.x.file.storage.core.recorder.FileRecorder;
+import org.dromara.x.file.storage.core.tika.ContentTypeDetect;
+import org.dromara.x.file.storage.core.tika.DefaultTikaFactory;
+import org.dromara.x.file.storage.core.tika.TikaContentTypeDetect;
+import org.dromara.x.file.storage.core.tika.TikaFactory;
+import org.dromara.x.file.storage.core.util.Tools;
import java.util.ArrayList;
import java.util.Collections;
@@ -37,8 +38,6 @@
import java.util.function.Supplier;
import java.util.stream.Collectors;
-import static cn.xuyanwu.spring.file.storage.util.Tools.cast;
-
@Slf4j
@Getter
@Setter
@@ -164,6 +163,19 @@ public FileStorageServiceBuilder addUriFileWrapperAdapter() {
return this;
}
+ /**
+ * 添加 HttpServletRequest 文件包装适配器
+ */
+ public FileStorageServiceBuilder addHttpServletRequestFileWrapperAdapter() {
+ if (!doesNotExistClass("javax.servlet.http.HttpServletRequest")) {
+ fileWrapperAdapterList.add(new JavaxHttpServletRequestFileWrapperAdapter());
+ }
+ if (!doesNotExistClass("jakarta.servlet.http.HttpServletRequest")) {
+ fileWrapperAdapterList.add(new JakartaHttpServletRequestFileWrapperAdapter());
+ }
+ return this;
+ }
+
/**
* 添加全部的文件包装适配器
*/
@@ -172,6 +184,7 @@ public FileStorageServiceBuilder addAllFileWrapperAdapter() {
addInputStreamFileWrapperAdapter();
addLocalFileWrapperAdapter();
addUriFileWrapperAdapter();
+ addHttpServletRequestFileWrapperAdapter();
return this;
}
@@ -248,6 +261,8 @@ public FileStorageService build() {
service.setFileRecorder(fileRecorder);
service.setDefaultPlatform(properties.getDefaultPlatform());
service.setThumbnailSuffix(properties.getThumbnailSuffix());
+ service.setUploadNotSupportMetadataThrowException(properties.getUploadNotSupportMetadataThrowException());
+ service.setUploadNotSupportAclThrowException(properties.getUploadNotSupportAclThrowException());
service.setAspectList(new CopyOnWriteArrayList<>(aspectList));
service.setFileWrapperAdapterList(new CopyOnWriteArrayList<>(fileWrapperAdapterList));
service.setContentTypeDetect(contentTypeDetect);
@@ -449,7 +464,7 @@ public static FileStorageClientFactory getFactory(String platfo
for (FileStorageClientFactory> factory : factoryList) {
if (Objects.equals(platform,factory.getPlatform())) {
try {
- return cast(factory);
+ return Tools.cast(factory);
} catch (Exception e) {
throw new FileStorageRuntimeException("获取 FileStorageClientFactory 失败,类型不匹配,platform:" + platform,e);
}
@@ -479,7 +494,7 @@ public static void buildFileStorageDetect(List> list,String platformName,Strin
if (CollUtil.isEmpty(list)) return;
for (String className : classNames) {
if (doesNotExistClass(className)) {
- throw new FileStorageRuntimeException("检测到" + platformName + "配置,但是没有找到对应的依赖类:" + className + ",所以无法加载此存储平台!配置参考地址:https://spring-file-storage.xuyanwu.cn/#/%E5%BF%AB%E9%80%9F%E5%85%A5%E9%97%A8");
+ throw new FileStorageRuntimeException("检测到" + platformName + "配置,但是没有找到对应的依赖类:" + className + ",所以无法加载此存储平台!配置参考地址:https://x-file-storage.xuyanwu.cn/#/%E5%BF%AB%E9%80%9F%E5%85%A5%E9%97%A8");
}
}
}
diff --git a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/IOExceptionConsumer.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/IOExceptionConsumer.java
similarity index 90%
rename from file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/IOExceptionConsumer.java
rename to x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/IOExceptionConsumer.java
index 1c0d1eca..c9917ce5 100644
--- a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/IOExceptionConsumer.java
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/IOExceptionConsumer.java
@@ -22,7 +22,7 @@
*
*
*/
-package cn.xuyanwu.spring.file.storage;
+package org.dromara.x.file.storage.core;
import java.io.IOException;
diff --git a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/IOExceptionFunction.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/IOExceptionFunction.java
similarity index 79%
rename from file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/IOExceptionFunction.java
rename to x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/IOExceptionFunction.java
index 9626d2cd..1bbdd427 100644
--- a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/IOExceptionFunction.java
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/IOExceptionFunction.java
@@ -1,4 +1,4 @@
-package cn.xuyanwu.spring.file.storage;
+package org.dromara.x.file.storage.core;
import java.io.IOException;
diff --git a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/ProgressInputStream.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/ProgressInputStream.java
similarity index 97%
rename from file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/ProgressInputStream.java
rename to x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/ProgressInputStream.java
index ff6675c9..e5f8a556 100644
--- a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/ProgressInputStream.java
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/ProgressInputStream.java
@@ -1,4 +1,4 @@
-package cn.xuyanwu.spring.file.storage;
+package org.dromara.x.file.storage.core;
import java.io.FilterInputStream;
import java.io.IOException;
diff --git a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/ProgressListener.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/ProgressListener.java
similarity index 90%
rename from file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/ProgressListener.java
rename to x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/ProgressListener.java
index eff383cd..405d3eca 100644
--- a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/ProgressListener.java
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/ProgressListener.java
@@ -1,4 +1,4 @@
-package cn.xuyanwu.spring.file.storage;
+package org.dromara.x.file.storage.core;
/**
* 进度监听器
diff --git a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/UploadPretreatment.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/UploadPretreatment.java
similarity index 76%
rename from file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/UploadPretreatment.java
rename to x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/UploadPretreatment.java
index 9cddbfab..ae0f5fe8 100644
--- a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/UploadPretreatment.java
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/UploadPretreatment.java
@@ -1,19 +1,21 @@
-package cn.xuyanwu.spring.file.storage;
+package org.dromara.x.file.storage.core;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.io.file.FileNameUtil;
import cn.hutool.core.lang.Dict;
-import cn.xuyanwu.spring.file.storage.exception.FileStorageRuntimeException;
-import cn.xuyanwu.spring.file.storage.file.FileWrapper;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
import net.coobird.thumbnailator.Thumbnails;
+import org.dromara.x.file.storage.core.exception.FileStorageRuntimeException;
+import org.dromara.x.file.storage.core.file.FileWrapper;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.util.LinkedHashMap;
+import java.util.Map;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
@@ -72,6 +74,36 @@ public class UploadPretreatment {
*/
private String thContentType;
+ /**
+ * 文件元数据
+ */
+ private Map metadata;
+
+ /**
+ * 文件用户元数据
+ */
+ private Map userMetadata;
+
+ /**
+ * 缩略图元数据
+ */
+ private Map thMetadata;
+
+ /**
+ * 缩略图用户元数据
+ */
+ private Map thUserMetadata;
+
+ /**
+ * 不支持元数据时抛出异常
+ */
+ private Boolean notSupportMetadataThrowException;
+
+ /**
+ * 不支持 ACL 时抛出异常
+ */
+ private Boolean notSupportAclThrowException;
+
/**
* 附加属性字典
*/
@@ -84,13 +116,13 @@ public class UploadPretreatment {
/**
* 文件的访问控制列表,一般情况下只有对象存储支持该功能
- * 详情见{@link cn.xuyanwu.spring.file.storage.FileInfo#setFileAcl}
+ * 详情见{@link FileInfo#setFileAcl}
*/
private Object fileAcl;
/**
* 缩略图的访问控制列表,一般情况下只有对象存储支持该功能
- * 详情见{@link cn.xuyanwu.spring.file.storage.FileInfo#setFileAcl}
+ * 详情见{@link FileInfo#setFileAcl}
*/
private Object thFileAcl;
@@ -260,6 +292,166 @@ public UploadPretreatment setOriginalFilename(String originalFilename) {
return this;
}
+ /**
+ * 获取文件元数据
+ */
+ public Map getMetadata() {
+ if (metadata == null) metadata = new LinkedHashMap<>();
+ return metadata;
+ }
+
+ /**
+ * 设置文件元数据
+ */
+ public UploadPretreatment putMetadata(boolean flag,String key,String value) {
+ if (flag) putMetadata(key,value);
+ return this;
+ }
+
+ /**
+ * 设置文件元数据
+ */
+ public UploadPretreatment putMetadata(String key,String value) {
+ getMetadata().put(key,value);
+ return this;
+ }
+
+ /**
+ * 设置文件元数据
+ */
+ public UploadPretreatment putMetadataAll(boolean flag,Map metadata) {
+ if (flag) putMetadataAll(metadata);
+ return this;
+ }
+
+ /**
+ * 设置文件元数据
+ */
+ public UploadPretreatment putMetadataAll(Map metadata) {
+ getMetadata().putAll(metadata);
+ return this;
+ }
+
+ /**
+ * 获取文件用户元数据
+ */
+ public Map getUserMetadata() {
+ if (userMetadata == null) userMetadata = new LinkedHashMap<>();
+ return userMetadata;
+ }
+
+ /**
+ * 设置文件用户元数据
+ */
+ public UploadPretreatment putUserMetadata(boolean flag,String key,String value) {
+ if (flag) putUserMetadata(key,value);
+ return this;
+ }
+
+ /**
+ * 设置文件用户元数据
+ */
+ public UploadPretreatment putUserMetadata(String key,String value) {
+ getUserMetadata().put(key,value);
+ return this;
+ }
+
+ /**
+ * 设置文件用户元数据
+ */
+ public UploadPretreatment putUserMetadataAll(boolean flag,Map metadata) {
+ if (flag) putUserMetadataAll(metadata);
+ return this;
+ }
+
+ /**
+ * 设置文件用户元数据
+ */
+ public UploadPretreatment putUserMetadataAll(Map metadata) {
+ getUserMetadata().putAll(metadata);
+ return this;
+ }
+
+ /**
+ * 获取缩略图元数据
+ */
+ public Map getThMetadata() {
+ if (thMetadata == null) thMetadata = new LinkedHashMap<>();
+ return thMetadata;
+ }
+
+ /**
+ * 设置缩略图元数据
+ */
+ public UploadPretreatment putThMetadata(boolean flag,String key,String value) {
+ if (flag) putThMetadata(key,value);
+ return this;
+ }
+
+ /**
+ * 设置缩略图元数据
+ */
+ public UploadPretreatment putThMetadata(String key,String value) {
+ getThMetadata().put(key,value);
+ return this;
+ }
+
+ /**
+ * 设置缩略图元数据
+ */
+ public UploadPretreatment putThMetadataAll(boolean flag,Map metadata) {
+ if (flag) putThMetadataAll(metadata);
+ return this;
+ }
+
+ /**
+ * 设置缩略图元数据
+ */
+ public UploadPretreatment putThMetadataAll(Map metadata) {
+ getThMetadata().putAll(metadata);
+ return this;
+ }
+
+ /**
+ * 获取缩略图用户元数据
+ */
+ public Map getThUserMetadata() {
+ if (thUserMetadata == null) thUserMetadata = new LinkedHashMap<>();
+ return thUserMetadata;
+ }
+
+ /**
+ * 设置缩略图用户元数据
+ */
+ public UploadPretreatment putThUserMetadata(boolean flag,String key,String value) {
+ if (flag) putThUserMetadata(key,value);
+ return this;
+ }
+
+ /**
+ * 设置缩略图用户元数据
+ */
+ public UploadPretreatment putThUserMetadata(String key,String value) {
+ getThUserMetadata().put(key,value);
+ return this;
+ }
+
+ /**
+ * 设置缩略图用户元数据
+ */
+ public UploadPretreatment putThUserMetadataAll(boolean flag,Map metadata) {
+ if (flag) putThUserMetadataAll(metadata);
+ return this;
+ }
+
+ /**
+ * 设置缩略图用户元数据
+ */
+ public UploadPretreatment putThUserMetadataAll(Map metadata) {
+ getThUserMetadata().putAll(metadata);
+ return this;
+ }
+
/**
* 获取附加属性字典
*/
@@ -284,6 +476,22 @@ public UploadPretreatment putAttr(String key,Object value) {
return this;
}
+ /**
+ * 设置附加属性
+ */
+ public UploadPretreatment putAttrAll(boolean flag,Map attr) {
+ if (flag) putAttrAll(attr);
+ return this;
+ }
+
+ /**
+ * 设置附加属性
+ */
+ public UploadPretreatment putAttrAll(Map attr) {
+ getAttr().putAll(attr);
+ return this;
+ }
+
/**
* 进行图片处理,可以进行裁剪、旋转、缩放、水印等操作
*/
@@ -498,7 +706,7 @@ public UploadPretreatment setProgressMonitor(Consumer progressListener) {
*
* @param progressListener 提供两个参数,第一个是 progressSize已传输字节数,第二个是 allSize总字节数
*/
- public UploadPretreatment setProgressMonitor(boolean flag,BiConsumer progressListener) {
+ public UploadPretreatment setProgressMonitor(boolean flag,BiConsumer progressListener) {
if (flag) setProgressMonitor(progressListener);
return this;
}
@@ -508,7 +716,7 @@ public UploadPretreatment setProgressMonitor(boolean flag,BiConsumer
*
* @param progressListener 提供两个参数,第一个是 progressSize已传输字节数,第二个是 allSize总字节数
*/
- public UploadPretreatment setProgressMonitor(BiConsumer progressListener) {
+ public UploadPretreatment setProgressMonitor(BiConsumer progressListener) {
return setProgressMonitor(new ProgressListener() {
@Override
public void start() {
@@ -543,7 +751,7 @@ public UploadPretreatment setProgressMonitor(ProgressListener progressListener)
/**
* 同时设置 fileAcl 和 thFileAcl 两个属性
- * 详情见{@link cn.xuyanwu.spring.file.storage.FileInfo#setFileAcl}
+ * 详情见{@link FileInfo#setFileAcl}
*/
public UploadPretreatment setAcl(boolean flag,Object acl) {
if (flag) setAcl(acl);
@@ -552,7 +760,7 @@ public UploadPretreatment setAcl(boolean flag,Object acl) {
/**
* 同时设置 fileAcl 和 thFileAcl 两个属性
- * 详情见{@link cn.xuyanwu.spring.file.storage.FileInfo#setFileAcl}
+ * 详情见{@link FileInfo#setFileAcl}
*/
public UploadPretreatment setAcl(Object acl) {
this.fileAcl = acl;
diff --git a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/aspect/DeleteAspectChain.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/DeleteAspectChain.java
similarity index 79%
rename from file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/aspect/DeleteAspectChain.java
rename to x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/DeleteAspectChain.java
index 4f12dfaa..46132e75 100644
--- a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/aspect/DeleteAspectChain.java
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/DeleteAspectChain.java
@@ -1,10 +1,10 @@
-package cn.xuyanwu.spring.file.storage.aspect;
+package org.dromara.x.file.storage.core.aspect;
-import cn.xuyanwu.spring.file.storage.FileInfo;
-import cn.xuyanwu.spring.file.storage.platform.FileStorage;
-import cn.xuyanwu.spring.file.storage.recorder.FileRecorder;
import lombok.Getter;
import lombok.Setter;
+import org.dromara.x.file.storage.core.FileInfo;
+import org.dromara.x.file.storage.core.platform.FileStorage;
+import org.dromara.x.file.storage.core.recorder.FileRecorder;
import java.util.Iterator;
diff --git a/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/DeleteAspectChainCallback.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/DeleteAspectChainCallback.java
new file mode 100644
index 00000000..a85cd240
--- /dev/null
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/DeleteAspectChainCallback.java
@@ -0,0 +1,12 @@
+package org.dromara.x.file.storage.core.aspect;
+
+import org.dromara.x.file.storage.core.FileInfo;
+import org.dromara.x.file.storage.core.platform.FileStorage;
+import org.dromara.x.file.storage.core.recorder.FileRecorder;
+
+/**
+ * 删除切面调用链结束回调
+ */
+public interface DeleteAspectChainCallback {
+ boolean run(FileInfo fileInfo,FileStorage fileStorage,FileRecorder fileRecorder);
+}
diff --git a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/aspect/DownloadAspectChain.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/DownloadAspectChain.java
similarity index 85%
rename from file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/aspect/DownloadAspectChain.java
rename to x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/DownloadAspectChain.java
index 45f8dcbe..552e512e 100644
--- a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/aspect/DownloadAspectChain.java
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/DownloadAspectChain.java
@@ -1,9 +1,9 @@
-package cn.xuyanwu.spring.file.storage.aspect;
+package org.dromara.x.file.storage.core.aspect;
-import cn.xuyanwu.spring.file.storage.FileInfo;
-import cn.xuyanwu.spring.file.storage.platform.FileStorage;
import lombok.Getter;
import lombok.Setter;
+import org.dromara.x.file.storage.core.FileInfo;
+import org.dromara.x.file.storage.core.platform.FileStorage;
import java.io.InputStream;
import java.util.Iterator;
diff --git a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/aspect/DownloadAspectChainCallback.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/DownloadAspectChainCallback.java
similarity index 61%
rename from file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/aspect/DownloadAspectChainCallback.java
rename to x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/DownloadAspectChainCallback.java
index 0c38c45e..24b450b3 100644
--- a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/aspect/DownloadAspectChainCallback.java
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/DownloadAspectChainCallback.java
@@ -1,7 +1,7 @@
-package cn.xuyanwu.spring.file.storage.aspect;
+package org.dromara.x.file.storage.core.aspect;
-import cn.xuyanwu.spring.file.storage.FileInfo;
-import cn.xuyanwu.spring.file.storage.platform.FileStorage;
+import org.dromara.x.file.storage.core.FileInfo;
+import org.dromara.x.file.storage.core.platform.FileStorage;
import java.io.InputStream;
import java.util.function.Consumer;
diff --git a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/aspect/DownloadThAspectChain.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/DownloadThAspectChain.java
similarity index 85%
rename from file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/aspect/DownloadThAspectChain.java
rename to x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/DownloadThAspectChain.java
index 3a94bd16..380b8adc 100644
--- a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/aspect/DownloadThAspectChain.java
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/DownloadThAspectChain.java
@@ -1,9 +1,9 @@
-package cn.xuyanwu.spring.file.storage.aspect;
+package org.dromara.x.file.storage.core.aspect;
-import cn.xuyanwu.spring.file.storage.FileInfo;
-import cn.xuyanwu.spring.file.storage.platform.FileStorage;
import lombok.Getter;
import lombok.Setter;
+import org.dromara.x.file.storage.core.FileInfo;
+import org.dromara.x.file.storage.core.platform.FileStorage;
import java.io.InputStream;
import java.util.Iterator;
diff --git a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/aspect/DownloadThAspectChainCallback.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/DownloadThAspectChainCallback.java
similarity index 62%
rename from file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/aspect/DownloadThAspectChainCallback.java
rename to x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/DownloadThAspectChainCallback.java
index e5621e2a..1397d8f2 100644
--- a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/aspect/DownloadThAspectChainCallback.java
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/DownloadThAspectChainCallback.java
@@ -1,7 +1,7 @@
-package cn.xuyanwu.spring.file.storage.aspect;
+package org.dromara.x.file.storage.core.aspect;
-import cn.xuyanwu.spring.file.storage.FileInfo;
-import cn.xuyanwu.spring.file.storage.platform.FileStorage;
+import org.dromara.x.file.storage.core.FileInfo;
+import org.dromara.x.file.storage.core.platform.FileStorage;
import java.io.InputStream;
import java.util.function.Consumer;
diff --git a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/aspect/ExistsAspectChain.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/ExistsAspectChain.java
similarity index 83%
rename from file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/aspect/ExistsAspectChain.java
rename to x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/ExistsAspectChain.java
index 224b1e88..4da7d593 100644
--- a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/aspect/ExistsAspectChain.java
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/ExistsAspectChain.java
@@ -1,9 +1,9 @@
-package cn.xuyanwu.spring.file.storage.aspect;
+package org.dromara.x.file.storage.core.aspect;
-import cn.xuyanwu.spring.file.storage.FileInfo;
-import cn.xuyanwu.spring.file.storage.platform.FileStorage;
import lombok.Getter;
import lombok.Setter;
+import org.dromara.x.file.storage.core.FileInfo;
+import org.dromara.x.file.storage.core.platform.FileStorage;
import java.util.Iterator;
diff --git a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/aspect/ExistsAspectChainCallback.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/ExistsAspectChainCallback.java
similarity index 51%
rename from file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/aspect/ExistsAspectChainCallback.java
rename to x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/ExistsAspectChainCallback.java
index 693a536a..0a99207f 100644
--- a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/aspect/ExistsAspectChainCallback.java
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/ExistsAspectChainCallback.java
@@ -1,7 +1,7 @@
-package cn.xuyanwu.spring.file.storage.aspect;
+package org.dromara.x.file.storage.core.aspect;
-import cn.xuyanwu.spring.file.storage.FileInfo;
-import cn.xuyanwu.spring.file.storage.platform.FileStorage;
+import org.dromara.x.file.storage.core.FileInfo;
+import org.dromara.x.file.storage.core.platform.FileStorage;
/**
* 文件是否存在切面调用链结束回调
diff --git a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/aspect/FileStorageAspect.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/FileStorageAspect.java
similarity index 87%
rename from file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/aspect/FileStorageAspect.java
rename to x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/FileStorageAspect.java
index 5eae998d..4a4832a1 100644
--- a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/aspect/FileStorageAspect.java
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/FileStorageAspect.java
@@ -1,9 +1,9 @@
-package cn.xuyanwu.spring.file.storage.aspect;
+package org.dromara.x.file.storage.core.aspect;
-import cn.xuyanwu.spring.file.storage.FileInfo;
-import cn.xuyanwu.spring.file.storage.UploadPretreatment;
-import cn.xuyanwu.spring.file.storage.platform.FileStorage;
-import cn.xuyanwu.spring.file.storage.recorder.FileRecorder;
+import org.dromara.x.file.storage.core.FileInfo;
+import org.dromara.x.file.storage.core.UploadPretreatment;
+import org.dromara.x.file.storage.core.platform.FileStorage;
+import org.dromara.x.file.storage.core.recorder.FileRecorder;
import java.io.InputStream;
import java.util.Date;
@@ -92,6 +92,13 @@ default boolean setThFileAcl(SetThFileAclAspectChain chain,FileInfo fileInfo,Obj
return chain.next(fileInfo,acl,fileStorage);
}
+ /**
+ * 是否支持 Metadata
+ */
+ default boolean isSupportMetadataAround(IsSupportMetadataAspectChain chain,FileStorage fileStorage) {
+ return chain.next(fileStorage);
+ }
+
/**
* 通过反射调用指定存储平台的方法
*/
diff --git a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/aspect/GeneratePresignedUrlAspectChain.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/GeneratePresignedUrlAspectChain.java
similarity index 85%
rename from file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/aspect/GeneratePresignedUrlAspectChain.java
rename to x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/GeneratePresignedUrlAspectChain.java
index 79075d8f..68493d33 100644
--- a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/aspect/GeneratePresignedUrlAspectChain.java
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/GeneratePresignedUrlAspectChain.java
@@ -1,9 +1,9 @@
-package cn.xuyanwu.spring.file.storage.aspect;
+package org.dromara.x.file.storage.core.aspect;
-import cn.xuyanwu.spring.file.storage.FileInfo;
-import cn.xuyanwu.spring.file.storage.platform.FileStorage;
import lombok.Getter;
import lombok.Setter;
+import org.dromara.x.file.storage.core.FileInfo;
+import org.dromara.x.file.storage.core.platform.FileStorage;
import java.util.Date;
import java.util.Iterator;
diff --git a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/aspect/GeneratePresignedUrlAspectChainCallback.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/GeneratePresignedUrlAspectChainCallback.java
similarity index 60%
rename from file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/aspect/GeneratePresignedUrlAspectChainCallback.java
rename to x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/GeneratePresignedUrlAspectChainCallback.java
index 9303fe41..61d2b348 100644
--- a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/aspect/GeneratePresignedUrlAspectChainCallback.java
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/GeneratePresignedUrlAspectChainCallback.java
@@ -1,7 +1,7 @@
-package cn.xuyanwu.spring.file.storage.aspect;
+package org.dromara.x.file.storage.core.aspect;
-import cn.xuyanwu.spring.file.storage.FileInfo;
-import cn.xuyanwu.spring.file.storage.platform.FileStorage;
+import org.dromara.x.file.storage.core.FileInfo;
+import org.dromara.x.file.storage.core.platform.FileStorage;
import java.util.Date;
diff --git a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/aspect/GenerateThPresignedUrlAspectChain.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/GenerateThPresignedUrlAspectChain.java
similarity index 86%
rename from file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/aspect/GenerateThPresignedUrlAspectChain.java
rename to x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/GenerateThPresignedUrlAspectChain.java
index dc9d6dfc..0694320c 100644
--- a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/aspect/GenerateThPresignedUrlAspectChain.java
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/GenerateThPresignedUrlAspectChain.java
@@ -1,9 +1,9 @@
-package cn.xuyanwu.spring.file.storage.aspect;
+package org.dromara.x.file.storage.core.aspect;
-import cn.xuyanwu.spring.file.storage.FileInfo;
-import cn.xuyanwu.spring.file.storage.platform.FileStorage;
import lombok.Getter;
import lombok.Setter;
+import org.dromara.x.file.storage.core.FileInfo;
+import org.dromara.x.file.storage.core.platform.FileStorage;
import java.util.Date;
import java.util.Iterator;
diff --git a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/aspect/GenerateThPresignedUrlAspectChainCallback.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/GenerateThPresignedUrlAspectChainCallback.java
similarity index 61%
rename from file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/aspect/GenerateThPresignedUrlAspectChainCallback.java
rename to x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/GenerateThPresignedUrlAspectChainCallback.java
index d4d4be58..2522e1d4 100644
--- a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/aspect/GenerateThPresignedUrlAspectChainCallback.java
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/GenerateThPresignedUrlAspectChainCallback.java
@@ -1,7 +1,7 @@
-package cn.xuyanwu.spring.file.storage.aspect;
+package org.dromara.x.file.storage.core.aspect;
-import cn.xuyanwu.spring.file.storage.FileInfo;
-import cn.xuyanwu.spring.file.storage.platform.FileStorage;
+import org.dromara.x.file.storage.core.FileInfo;
+import org.dromara.x.file.storage.core.platform.FileStorage;
import java.util.Date;
diff --git a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/aspect/InvokeAspectChain.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/InvokeAspectChain.java
similarity index 88%
rename from file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/aspect/InvokeAspectChain.java
rename to x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/InvokeAspectChain.java
index 4353634b..1144f0f0 100644
--- a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/aspect/InvokeAspectChain.java
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/InvokeAspectChain.java
@@ -1,8 +1,8 @@
-package cn.xuyanwu.spring.file.storage.aspect;
+package org.dromara.x.file.storage.core.aspect;
-import cn.xuyanwu.spring.file.storage.platform.FileStorage;
import lombok.Getter;
import lombok.Setter;
+import org.dromara.x.file.storage.core.platform.FileStorage;
import java.util.Iterator;
diff --git a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/aspect/InvokeAspectChainCallback.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/InvokeAspectChainCallback.java
similarity index 65%
rename from file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/aspect/InvokeAspectChainCallback.java
rename to x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/InvokeAspectChainCallback.java
index 7e231e1d..2d89da5a 100644
--- a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/aspect/InvokeAspectChainCallback.java
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/InvokeAspectChainCallback.java
@@ -1,6 +1,6 @@
-package cn.xuyanwu.spring.file.storage.aspect;
+package org.dromara.x.file.storage.core.aspect;
-import cn.xuyanwu.spring.file.storage.platform.FileStorage;
+import org.dromara.x.file.storage.core.platform.FileStorage;
/**
* 通过反射调用指定存储平台的方法的切面调用链结束回调
diff --git a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/aspect/IsSupportAclAspectChain.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/IsSupportAclAspectChain.java
similarity index 88%
rename from file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/aspect/IsSupportAclAspectChain.java
rename to x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/IsSupportAclAspectChain.java
index d908c7ff..9f678509 100644
--- a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/aspect/IsSupportAclAspectChain.java
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/IsSupportAclAspectChain.java
@@ -1,8 +1,8 @@
-package cn.xuyanwu.spring.file.storage.aspect;
+package org.dromara.x.file.storage.core.aspect;
-import cn.xuyanwu.spring.file.storage.platform.FileStorage;
import lombok.Getter;
import lombok.Setter;
+import org.dromara.x.file.storage.core.platform.FileStorage;
import java.util.Iterator;
diff --git a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/aspect/IsSupportAclAspectChainCallback.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/IsSupportAclAspectChainCallback.java
similarity index 61%
rename from file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/aspect/IsSupportAclAspectChainCallback.java
rename to x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/IsSupportAclAspectChainCallback.java
index e24ba0ee..c408857b 100644
--- a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/aspect/IsSupportAclAspectChainCallback.java
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/IsSupportAclAspectChainCallback.java
@@ -1,6 +1,6 @@
-package cn.xuyanwu.spring.file.storage.aspect;
+package org.dromara.x.file.storage.core.aspect;
-import cn.xuyanwu.spring.file.storage.platform.FileStorage;
+import org.dromara.x.file.storage.core.platform.FileStorage;
/**
* 是否支持文件的访问控制列表 切面调用链结束回调
diff --git a/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/IsSupportMetadataAspectChain.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/IsSupportMetadataAspectChain.java
new file mode 100644
index 00000000..dd55462a
--- /dev/null
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/IsSupportMetadataAspectChain.java
@@ -0,0 +1,34 @@
+package org.dromara.x.file.storage.core.aspect;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.dromara.x.file.storage.core.platform.FileStorage;
+
+import java.util.Iterator;
+
+/**
+ * 是否支持 Metadata 的切面调用链
+ */
+@Getter
+@Setter
+public class IsSupportMetadataAspectChain {
+
+ private IsSupportMetadataAspectChainCallback callback;
+ private Iterator aspectIterator;
+
+ public IsSupportMetadataAspectChain(Iterable aspects,IsSupportMetadataAspectChainCallback callback) {
+ this.aspectIterator = aspects.iterator();
+ this.callback = callback;
+ }
+
+ /**
+ * 调用下一个切面
+ */
+ public boolean next(FileStorage fileStorage) {
+ if (aspectIterator.hasNext()) {//还有下一个
+ return aspectIterator.next().isSupportMetadataAround(this,fileStorage);
+ } else {
+ return callback.run(fileStorage);
+ }
+ }
+}
diff --git a/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/IsSupportMetadataAspectChainCallback.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/IsSupportMetadataAspectChainCallback.java
new file mode 100644
index 00000000..a38c2a4e
--- /dev/null
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/IsSupportMetadataAspectChainCallback.java
@@ -0,0 +1,10 @@
+package org.dromara.x.file.storage.core.aspect;
+
+import org.dromara.x.file.storage.core.platform.FileStorage;
+
+/**
+ * 是否支持 Metadata 切面调用链结束回调
+ */
+public interface IsSupportMetadataAspectChainCallback {
+ boolean run(FileStorage fileStorage);
+}
diff --git a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/aspect/IsSupportPresignedUrlAspectChain.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/IsSupportPresignedUrlAspectChain.java
similarity index 89%
rename from file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/aspect/IsSupportPresignedUrlAspectChain.java
rename to x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/IsSupportPresignedUrlAspectChain.java
index 9747e276..d1b102a1 100644
--- a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/aspect/IsSupportPresignedUrlAspectChain.java
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/IsSupportPresignedUrlAspectChain.java
@@ -1,8 +1,8 @@
-package cn.xuyanwu.spring.file.storage.aspect;
+package org.dromara.x.file.storage.core.aspect;
-import cn.xuyanwu.spring.file.storage.platform.FileStorage;
import lombok.Getter;
import lombok.Setter;
+import org.dromara.x.file.storage.core.platform.FileStorage;
import java.util.Iterator;
diff --git a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/aspect/IsSupportPresignedUrlAspectChainCallback.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/IsSupportPresignedUrlAspectChainCallback.java
similarity index 64%
rename from file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/aspect/IsSupportPresignedUrlAspectChainCallback.java
rename to x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/IsSupportPresignedUrlAspectChainCallback.java
index 4f5b1dfa..83dc6c63 100644
--- a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/aspect/IsSupportPresignedUrlAspectChainCallback.java
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/IsSupportPresignedUrlAspectChainCallback.java
@@ -1,6 +1,6 @@
-package cn.xuyanwu.spring.file.storage.aspect;
+package org.dromara.x.file.storage.core.aspect;
-import cn.xuyanwu.spring.file.storage.platform.FileStorage;
+import org.dromara.x.file.storage.core.platform.FileStorage;
/**
* 是否支持对文件生成可以签名访问的 URL 切面调用链结束回调
diff --git a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/aspect/SetFileAclAspectChain.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/SetFileAclAspectChain.java
similarity index 84%
rename from file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/aspect/SetFileAclAspectChain.java
rename to x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/SetFileAclAspectChain.java
index c1a29237..f8a1f3c3 100644
--- a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/aspect/SetFileAclAspectChain.java
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/SetFileAclAspectChain.java
@@ -1,9 +1,9 @@
-package cn.xuyanwu.spring.file.storage.aspect;
+package org.dromara.x.file.storage.core.aspect;
-import cn.xuyanwu.spring.file.storage.FileInfo;
-import cn.xuyanwu.spring.file.storage.platform.FileStorage;
import lombok.Getter;
import lombok.Setter;
+import org.dromara.x.file.storage.core.FileInfo;
+import org.dromara.x.file.storage.core.platform.FileStorage;
import java.util.Iterator;
diff --git a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/aspect/SetFileAclAspectChainCallback.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/SetFileAclAspectChainCallback.java
similarity index 54%
rename from file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/aspect/SetFileAclAspectChainCallback.java
rename to x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/SetFileAclAspectChainCallback.java
index 2a012344..7f49c808 100644
--- a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/aspect/SetFileAclAspectChainCallback.java
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/SetFileAclAspectChainCallback.java
@@ -1,7 +1,7 @@
-package cn.xuyanwu.spring.file.storage.aspect;
+package org.dromara.x.file.storage.core.aspect;
-import cn.xuyanwu.spring.file.storage.FileInfo;
-import cn.xuyanwu.spring.file.storage.platform.FileStorage;
+import org.dromara.x.file.storage.core.FileInfo;
+import org.dromara.x.file.storage.core.platform.FileStorage;
/**
* 获取文件的访问控制列表调用链结束回调
diff --git a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/aspect/SetThFileAclAspectChain.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/SetThFileAclAspectChain.java
similarity index 84%
rename from file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/aspect/SetThFileAclAspectChain.java
rename to x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/SetThFileAclAspectChain.java
index 6ebfdfec..1ca1211e 100644
--- a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/aspect/SetThFileAclAspectChain.java
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/SetThFileAclAspectChain.java
@@ -1,9 +1,9 @@
-package cn.xuyanwu.spring.file.storage.aspect;
+package org.dromara.x.file.storage.core.aspect;
-import cn.xuyanwu.spring.file.storage.FileInfo;
-import cn.xuyanwu.spring.file.storage.platform.FileStorage;
import lombok.Getter;
import lombok.Setter;
+import org.dromara.x.file.storage.core.FileInfo;
+import org.dromara.x.file.storage.core.platform.FileStorage;
import java.util.Iterator;
diff --git a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/aspect/SetThFileAclAspectChainCallback.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/SetThFileAclAspectChainCallback.java
similarity index 55%
rename from file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/aspect/SetThFileAclAspectChainCallback.java
rename to x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/SetThFileAclAspectChainCallback.java
index eb5f1615..1f7df27b 100644
--- a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/aspect/SetThFileAclAspectChainCallback.java
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/SetThFileAclAspectChainCallback.java
@@ -1,7 +1,7 @@
-package cn.xuyanwu.spring.file.storage.aspect;
+package org.dromara.x.file.storage.core.aspect;
-import cn.xuyanwu.spring.file.storage.FileInfo;
-import cn.xuyanwu.spring.file.storage.platform.FileStorage;
+import org.dromara.x.file.storage.core.FileInfo;
+import org.dromara.x.file.storage.core.platform.FileStorage;
/**
* 设置缩略图文件的访问控制列表调用链结束回调
diff --git a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/aspect/UploadAspectChain.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/UploadAspectChain.java
similarity index 76%
rename from file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/aspect/UploadAspectChain.java
rename to x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/UploadAspectChain.java
index f3e47592..bed71639 100644
--- a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/aspect/UploadAspectChain.java
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/UploadAspectChain.java
@@ -1,11 +1,11 @@
-package cn.xuyanwu.spring.file.storage.aspect;
+package org.dromara.x.file.storage.core.aspect;
-import cn.xuyanwu.spring.file.storage.FileInfo;
-import cn.xuyanwu.spring.file.storage.UploadPretreatment;
-import cn.xuyanwu.spring.file.storage.platform.FileStorage;
-import cn.xuyanwu.spring.file.storage.recorder.FileRecorder;
import lombok.Getter;
import lombok.Setter;
+import org.dromara.x.file.storage.core.FileInfo;
+import org.dromara.x.file.storage.core.UploadPretreatment;
+import org.dromara.x.file.storage.core.platform.FileStorage;
+import org.dromara.x.file.storage.core.recorder.FileRecorder;
import java.util.Iterator;
diff --git a/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/UploadAspectChainCallback.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/UploadAspectChainCallback.java
new file mode 100644
index 00000000..aaf182ad
--- /dev/null
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/aspect/UploadAspectChainCallback.java
@@ -0,0 +1,13 @@
+package org.dromara.x.file.storage.core.aspect;
+
+import org.dromara.x.file.storage.core.FileInfo;
+import org.dromara.x.file.storage.core.UploadPretreatment;
+import org.dromara.x.file.storage.core.platform.FileStorage;
+import org.dromara.x.file.storage.core.recorder.FileRecorder;
+
+/**
+ * 上传切面调用链结束回调
+ */
+public interface UploadAspectChainCallback {
+ FileInfo run(FileInfo fileInfo,UploadPretreatment pre,FileStorage fileStorage,FileRecorder fileRecorder);
+}
diff --git a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/constant/Constant.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/constant/Constant.java
similarity index 63%
rename from file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/constant/Constant.java
rename to x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/constant/Constant.java
index c8df45a7..9265df2d 100644
--- a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/constant/Constant.java
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/constant/Constant.java
@@ -1,4 +1,4 @@
-package cn.xuyanwu.spring.file.storage.constant;
+package org.dromara.x.file.storage.core.constant;
public interface Constant {
@@ -86,4 +86,30 @@ interface GoogleCloudStorageACL extends ACL {
String BUCKET_OWNER_READ = "bucket-owner-read";
String BUCKET_OWNER_FULL_CONTROL = "bucket-owner-full-control";
}
+
+
+ /**
+ * 元数据名称,这里列举的是一些相对通用的名称,但不一定每个存储平台都支持,具体支持情况自行查阅对应存储的相关文档
+ * 阿里云 OSS {@link com.aliyun.oss.model.ObjectMetadata} {@link com.aliyun.oss.internal.OSSHeaders}
+ * Amazon S3 {@link com.amazonaws.services.s3.model.ObjectMetadata} {@link com.amazonaws.services.s3.Headers}
+ * 华为云 OBS {@link com.obs.services.model.ObjectMetadata }
+ * 百度云 BOS {@link com.baidubce.services.bos.model.ObjectMetadata }
+ * 腾讯云 COS {@link com.qcloud.cos.model.ObjectMetadata }
+ * 七牛云 Kodo https://developer.qiniu.com/kodo/1312/upload
+ * 又拍云 USS {@link com.upyun.RestManager.PARAMS}
+ * MinIO {@link io.minio.ObjectWriteArgs}
+ * GoogleCloud Storage {@link com.google.cloud.storage.BlobInfo} {@link com.google.cloud.storage.Storage.BlobField}
+ */
+ interface Metadata {
+ String CACHE_CONTROL = "Cache-Control";
+ String CONTENT_DISPOSITION = "Content-Disposition";
+ String CONTENT_ENCODING = "Content-Encoding";
+ String CONTENT_LENGTH = "Content-Length";
+ String CONTENT_MD5 = "Content-MD5";
+ String CONTENT_TYPE = "Content-Type";
+ String CONTENT_LANGUAGE = "Content-Language";
+ String EXPIRES = "Expires";
+ String LAST_MODIFIED = "Last-Modified";
+ }
+
}
diff --git a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/exception/FileStorageRuntimeException.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/exception/FileStorageRuntimeException.java
similarity index 92%
rename from file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/exception/FileStorageRuntimeException.java
rename to x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/exception/FileStorageRuntimeException.java
index ffd7895b..7a703de4 100644
--- a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/exception/FileStorageRuntimeException.java
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/exception/FileStorageRuntimeException.java
@@ -1,4 +1,4 @@
-package cn.xuyanwu.spring.file.storage.exception;
+package org.dromara.x.file.storage.core.exception;
/**
* FileStorage 运行时异常
diff --git a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/file/ByteFileWrapper.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/file/ByteFileWrapper.java
similarity index 94%
rename from file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/file/ByteFileWrapper.java
rename to x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/file/ByteFileWrapper.java
index 0fd373c3..8d399b0c 100644
--- a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/file/ByteFileWrapper.java
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/file/ByteFileWrapper.java
@@ -1,4 +1,4 @@
-package cn.xuyanwu.spring.file.storage.file;
+package org.dromara.x.file.storage.core.file;
import lombok.Getter;
import lombok.NoArgsConstructor;
diff --git a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/file/ByteFileWrapperAdapter.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/file/ByteFileWrapperAdapter.java
similarity index 90%
rename from file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/file/ByteFileWrapperAdapter.java
rename to x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/file/ByteFileWrapperAdapter.java
index 1b927bd7..55674c34 100644
--- a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/file/ByteFileWrapperAdapter.java
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/file/ByteFileWrapperAdapter.java
@@ -1,10 +1,10 @@
-package cn.xuyanwu.spring.file.storage.file;
+package org.dromara.x.file.storage.core.file;
-import cn.xuyanwu.spring.file.storage.tika.ContentTypeDetect;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
+import org.dromara.x.file.storage.core.tika.ContentTypeDetect;
/**
* byte[] 文件包装适配器
diff --git a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/file/FileWrapper.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/file/FileWrapper.java
similarity index 87%
rename from file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/file/FileWrapper.java
rename to x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/file/FileWrapper.java
index 8c00abfa..596ee4e2 100644
--- a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/file/FileWrapper.java
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/file/FileWrapper.java
@@ -1,9 +1,9 @@
-package cn.xuyanwu.spring.file.storage.file;
+package org.dromara.x.file.storage.core.file;
-import cn.xuyanwu.spring.file.storage.IOExceptionConsumer;
-import cn.xuyanwu.spring.file.storage.IOExceptionFunction;
-import cn.xuyanwu.spring.file.storage.exception.FileStorageRuntimeException;
+import org.dromara.x.file.storage.core.IOExceptionConsumer;
+import org.dromara.x.file.storage.core.IOExceptionFunction;
+import org.dromara.x.file.storage.core.exception.FileStorageRuntimeException;
import java.io.File;
import java.io.IOException;
diff --git a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/file/FileWrapperAdapter.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/file/FileWrapperAdapter.java
similarity index 93%
rename from file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/file/FileWrapperAdapter.java
rename to x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/file/FileWrapperAdapter.java
index cbc852c8..d2f3c017 100644
--- a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/file/FileWrapperAdapter.java
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/file/FileWrapperAdapter.java
@@ -1,4 +1,4 @@
-package cn.xuyanwu.spring.file.storage.file;
+package org.dromara.x.file.storage.core.file;
import java.io.IOException;
diff --git a/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/file/HttpServletRequestFileWrapper.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/file/HttpServletRequestFileWrapper.java
new file mode 100644
index 00000000..7c43514f
--- /dev/null
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/file/HttpServletRequestFileWrapper.java
@@ -0,0 +1,53 @@
+package org.dromara.x.file.storage.core.file;
+
+import cn.hutool.core.io.IoUtil;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import org.dromara.x.file.storage.core.file.MultipartFormDataReader.MultipartFormData;
+
+import java.io.InputStream;
+
+/**
+ * JavaxHttpServletRequest 文件包装类
+ */
+@Getter
+@Setter
+@NoArgsConstructor
+public class HttpServletRequestFileWrapper implements FileWrapper {
+ private String name;
+ private String contentType;
+ private InputStream inputStream;
+ private Long size;
+ private MultipartFormData multipartFormData;
+
+
+ public HttpServletRequestFileWrapper(InputStream inputStream,String name,String contentType,Long size,MultipartFormData multipartFormData) {
+ this.name = name;
+ this.contentType = contentType;
+ this.inputStream = IoUtil.toMarkSupportStream(inputStream);
+ this.size = size;
+ this.multipartFormData = multipartFormData;
+ }
+
+ @Override
+ public InputStream getInputStream() {
+ return inputStream;
+ }
+
+ /**
+ * 获取参数值
+ */
+ public String getParameter(String name) {
+ return multipartFormData.getParameter(name);
+ }
+
+ /**
+ * 获取多个参数值
+ */
+ public String[] getParameterValues(String name) {
+ return multipartFormData.getParameterValues(name);
+
+ }
+
+}
diff --git a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/file/InputStreamFileWrapper.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/file/InputStreamFileWrapper.java
similarity index 94%
rename from file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/file/InputStreamFileWrapper.java
rename to x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/file/InputStreamFileWrapper.java
index d4fe56fa..be7c23a5 100644
--- a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/file/InputStreamFileWrapper.java
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/file/InputStreamFileWrapper.java
@@ -1,4 +1,4 @@
-package cn.xuyanwu.spring.file.storage.file;
+package org.dromara.x.file.storage.core.file;
import cn.hutool.core.io.IoUtil;
import lombok.Getter;
diff --git a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/file/InputStreamFileWrapperAdapter.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/file/InputStreamFileWrapperAdapter.java
similarity index 92%
rename from file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/file/InputStreamFileWrapperAdapter.java
rename to x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/file/InputStreamFileWrapperAdapter.java
index eb9c3353..5ceb32a1 100644
--- a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/file/InputStreamFileWrapperAdapter.java
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/file/InputStreamFileWrapperAdapter.java
@@ -1,12 +1,12 @@
-package cn.xuyanwu.spring.file.storage.file;
+package org.dromara.x.file.storage.core.file;
-import cn.xuyanwu.spring.file.storage.tika.ContentTypeDetect;
-import cn.xuyanwu.spring.file.storage.util.Tools;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
+import org.dromara.x.file.storage.core.tika.ContentTypeDetect;
+import org.dromara.x.file.storage.core.util.Tools;
import java.io.IOException;
import java.io.InputStream;
diff --git a/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/file/JakartaHttpServletRequestFileWrapperAdapter.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/file/JakartaHttpServletRequestFileWrapperAdapter.java
new file mode 100644
index 00000000..e7ec3dc8
--- /dev/null
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/file/JakartaHttpServletRequestFileWrapperAdapter.java
@@ -0,0 +1,47 @@
+package org.dromara.x.file.storage.core.file;
+
+import jakarta.servlet.http.HttpServletRequest;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.extern.slf4j.Slf4j;
+import org.dromara.x.file.storage.core.file.MultipartFormDataReader.MultipartFormData;
+
+import java.io.IOException;
+import java.nio.charset.Charset;
+
+/**
+ * 针对 jakarta 的 HttpServletRequest 文件包装适配器
+ */
+@Slf4j
+@Getter
+@Setter
+public class JakartaHttpServletRequestFileWrapperAdapter implements FileWrapperAdapter {
+
+ @Override
+ public boolean isSupport(Object source) {
+ if (source instanceof HttpServletRequest) {
+ HttpServletRequest request = (HttpServletRequest) source;
+ String contentType = request.getContentType();
+ return contentType != null && contentType.toLowerCase().trim().startsWith("multipart/form-data");
+ }
+ return source instanceof HttpServletRequestFileWrapper;
+ }
+
+ @Override
+ public FileWrapper getFileWrapper(Object source,String name,String contentType,Long size) throws IOException {
+ if (source instanceof HttpServletRequestFileWrapper) {
+ return updateFileWrapper((HttpServletRequestFileWrapper) source,name,contentType,size);
+ } else {
+ HttpServletRequest request = (HttpServletRequest) source;
+ Charset charset = Charset.forName(request.getCharacterEncoding());
+ MultipartFormData data = MultipartFormDataReader.read(request.getContentType(),request.getInputStream(),charset,request.getContentLengthLong());
+
+ if (name == null) name = data.getFileOriginalFilename();
+ if (contentType == null) contentType = data.getFileContentType();
+ if (size == null) size = data.getFileSize();
+ return new HttpServletRequestFileWrapper(data.getInputStream(),name,contentType,size,data);
+ }
+ }
+
+
+}
diff --git a/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/file/JavaxHttpServletRequestFileWrapperAdapter.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/file/JavaxHttpServletRequestFileWrapperAdapter.java
new file mode 100644
index 00000000..c04c8a38
--- /dev/null
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/file/JavaxHttpServletRequestFileWrapperAdapter.java
@@ -0,0 +1,47 @@
+package org.dromara.x.file.storage.core.file;
+
+import lombok.Getter;
+import lombok.Setter;
+import lombok.extern.slf4j.Slf4j;
+import org.dromara.x.file.storage.core.file.MultipartFormDataReader.MultipartFormData;
+
+import javax.servlet.http.HttpServletRequest;
+import java.io.IOException;
+import java.nio.charset.Charset;
+
+/**
+ * 针对 javax 的 HttpServletRequest 文件包装适配器
+ */
+@Slf4j
+@Getter
+@Setter
+public class JavaxHttpServletRequestFileWrapperAdapter implements FileWrapperAdapter {
+
+ @Override
+ public boolean isSupport(Object source) {
+ if (source instanceof HttpServletRequest) {
+ HttpServletRequest request = (HttpServletRequest) source;
+ String contentType = request.getContentType();
+ return contentType != null && contentType.toLowerCase().trim().startsWith("multipart/form-data");
+ }
+ return source instanceof HttpServletRequestFileWrapper;
+ }
+
+ @Override
+ public FileWrapper getFileWrapper(Object source,String name,String contentType,Long size) throws IOException {
+ if (source instanceof HttpServletRequestFileWrapper) {
+ return updateFileWrapper((HttpServletRequestFileWrapper) source,name,contentType,size);
+ } else {
+ HttpServletRequest request = (HttpServletRequest) source;
+ Charset charset = Charset.forName(request.getCharacterEncoding());
+ MultipartFormData data = MultipartFormDataReader.read(request.getContentType(),request.getInputStream(),charset,request.getContentLengthLong());
+
+ if (name == null) name = data.getFileOriginalFilename();
+ if (contentType == null) contentType = data.getFileContentType();
+ if (size == null) size = data.getFileSize();
+ return new HttpServletRequestFileWrapper(data.getInputStream(),name,contentType,size,data);
+ }
+ }
+
+
+}
diff --git a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/file/LocalFileWrapper.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/file/LocalFileWrapper.java
similarity index 95%
rename from file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/file/LocalFileWrapper.java
rename to x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/file/LocalFileWrapper.java
index 53824d0b..5147bb53 100644
--- a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/file/LocalFileWrapper.java
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/file/LocalFileWrapper.java
@@ -1,4 +1,4 @@
-package cn.xuyanwu.spring.file.storage.file;
+package org.dromara.x.file.storage.core.file;
import lombok.Getter;
import lombok.NoArgsConstructor;
diff --git a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/file/LocalFileWrapperAdapter.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/file/LocalFileWrapperAdapter.java
similarity index 91%
rename from file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/file/LocalFileWrapperAdapter.java
rename to x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/file/LocalFileWrapperAdapter.java
index 66201aa5..248afc6d 100644
--- a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/file/LocalFileWrapperAdapter.java
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/file/LocalFileWrapperAdapter.java
@@ -1,10 +1,10 @@
-package cn.xuyanwu.spring.file.storage.file;
+package org.dromara.x.file.storage.core.file;
-import cn.xuyanwu.spring.file.storage.tika.ContentTypeDetect;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
+import org.dromara.x.file.storage.core.tika.ContentTypeDetect;
import java.io.File;
import java.io.IOException;
diff --git a/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/file/MultipartFormDataReader.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/file/MultipartFormDataReader.java
new file mode 100644
index 00000000..9187db82
--- /dev/null
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/file/MultipartFormDataReader.java
@@ -0,0 +1,388 @@
+package org.dromara.x.file.storage.core.file;
+
+import cn.hutool.core.io.IoUtil;
+import cn.hutool.core.util.ArrayUtil;
+import cn.hutool.core.util.StrUtil;
+import lombok.Getter;
+import org.dromara.x.file.storage.core.exception.FileStorageRuntimeException;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.Charset;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * multipart/form-data 读取器
+ */
+public class MultipartFormDataReader {
+ /**
+ * 读取时缓冲区长度,默认 128KB
+ */
+ public static int BUFFER_LENGTH = 128 * 1024;
+
+
+ /**
+ * 读取 HttpServletRequest 中 InputStream 的数据,仅支持 multipart/form-data 格式的请求,需要注意以下几点:
+ * 1.要上传的文件参数位置必须是最后一个。
+ * 2.如果要有缩略图文件一起上传,缩略图所在的参数位置必须为倒数第二个,且必须传入参数 _hasTh 值为 true。
+ * 3.要上传的文件大小会自动推断,但是某些情况下可能推断错误,导致上传的文件出现问题,所以最好传入 _fileSize 参数,值为文件大小
+ * 4.除此之外不能出现任何文件参数
+ *
+ * @param contentType 请求类型
+ * @param inputStream 输入流
+ * @param charset 字符集
+ * @param contentLength 请求正文部分的长度
+ */
+ public static MultipartFormData read(String contentType,InputStream inputStream,Charset charset,Long contentLength) throws IOException {
+
+ String boundary = Boundary.getBoundary(contentType);
+ if (boundary == null)
+ throw new FileStorageRuntimeException("HttpServletRequest 的 ContentType 中未读取到 boundary 参数!");
+ MultipartFormData data = new MultipartFormData();
+ data.inputStream = IoUtil.toMarkSupportStream(inputStream);
+ data.charset = charset;
+ data.contentLength = contentLength;
+ data.buffer = new byte[BUFFER_LENGTH];
+ data.parameterMap = new LinkedHashMap<>();
+
+
+ //multipart/form-data; boundary=----WebKitFormBoundary0iQfWrHD6Yl9PNRe
+
+
+ //------WebKitFormBoundary0iQfWrHD6Yl9PNRe
+ //Content-Disposition: form-data; name="isPrivate"
+ //
+ //false
+ //------WebKitFormBoundary0iQfWrHD6Yl9PNRe
+ //Content-Disposition: form-data; name="saveFilename"
+ //
+ //
+ //------WebKitFormBoundary0iQfWrHD6Yl9PNRe
+ //Content-Disposition: form-data; name="files"; filename="a.png"
+ //Content-Type: image/png
+ //
+ //
+ //------WebKitFormBoundary0iQfWrHD6Yl9PNRe--
+ //
+
+
+ //读取Part分隔行
+ do {
+ data.boundary = Boundary.create(readLineBytes(data),boundary,charset);
+ } while (data.boundary == null);
+
+ //循环读取每个 Part 直到找到要上传的文件为止
+ while (true) {
+ if (readPart(data) == 3) break;
+ }
+ return data;
+ }
+
+ /**
+ * 读取 Part 并返回类型:1普通参数,2缩略图文件,3要上传的文件
+ */
+ public static int readPart(MultipartFormData data) throws IOException {
+ HashMap headerMap = new HashMap<>();
+ //读取 Part 的 Header 部分
+ while (true) {
+ String line = new String(readLineBytes(data),data.charset);
+ if (StrUtil.isBlank(line)) break;//头部已读完
+ int splitIndex = line.indexOf(": ");
+ if (splitIndex < 0) {
+ headerMap.put(line.trim().toLowerCase(),"");
+ } else {
+ String name = line.substring(0,splitIndex).trim().toLowerCase();
+ String value = line.substring(splitIndex + 1).trim();
+ headerMap.put(name,value);
+ }
+ }
+
+ //读取解析 Part 的内容定义参数
+ String disposition = headerMap.get("content-disposition");
+ if (StrUtil.isEmpty(disposition))
+ throw new FileStorageRuntimeException("HttpServletRequest 的 Part 无法识别 content-disposition");
+ LinkedHashMap dispositionMap = convertPartHeaderValue(disposition);
+ MultipartFormDataPartInputStream pin = new MultipartFormDataPartInputStream(data);
+
+ if (dispositionMap.containsKey("filename")) {//此参数有值,表示这部分是个文件
+ if ("true".equals(data.getParameter("_hasTh")) && data.thFileBytes == null) {//缩略图文件
+ data.thFileContentType = headerMap.get("content-type");
+ data.thFileBytes = IoUtil.readBytes(pin);
+ data.thFileOriginalFilename = dispositionMap.get("filename");
+ return 2;
+ } else {//要上传文件文件主体
+ data.fileContentType = headerMap.get("content-type");
+ data.fileInputStream = pin;
+ data.fileOriginalFilename = dispositionMap.get("filename");
+ //这里处理文件大小,如果参数中提供了,则使用参数中的
+ //否则通过流的总长度减去已读取长度和最后一个分割行及空行的长度,从而推算出这个文件的大小
+ //但是这样有个弊端,就是这个文件的参数位置必须是最后一个,否则将计算错误
+ String fileSize = data.getParameter("_fileSize");
+ if (StrUtil.isNotBlank(fileSize)) {
+ data.fileSize = Long.parseLong(fileSize);
+ } else {
+ data.fileSize = data.contentLength - data.totalReadLength - data.boundary.footerByteLength;
+ }
+ return 3;
+ }
+ } else {//解析成普通参数
+ String name = dispositionMap.get("name");
+ String value = IoUtil.read(pin,data.charset);
+ String[] values = data.parameterMap.get(name);
+ values = values == null ? new String[]{value} : ArrayUtil.append(values,value);
+ data.parameterMap.put(name,values);
+ return 1;
+ }
+
+ }
+
+ /**
+ * 简易版的 Header 值解析方法,直接按照分隔符解析,如果分隔符是参数名称或值的一部分,则解析会出现问题
+ */
+ public static LinkedHashMap convertPartHeaderValue(String text) {
+ return Arrays.stream(text.split(";"))
+ .map(String::trim)
+ .filter(StrUtil::isNotBlank)
+ .map(v -> {
+ String name, value;
+ int splitIndex = v.indexOf("=");
+ if (splitIndex < 0) {
+ name = v.trim().toLowerCase();
+ value = "";
+ } else {
+ name = v.substring(0,splitIndex).trim().toLowerCase();
+ value = v.substring(splitIndex + 1).trim();
+ if (value.length() > 1 && value.startsWith("\"") && value.endsWith("\"")) {
+ value = value.substring(1,value.length() - 1);
+ }
+ }
+ return new String[]{name,value};
+ }).collect(Collectors.toMap(v -> v[0],v -> v[1],(o,n) -> n,LinkedHashMap::new));
+ }
+
+
+ /**
+ * 读入一行字节数组
+ */
+ public static byte[] readLineBytes(MultipartFormData data) throws IOException {
+ int readLength = readLine(data.inputStream,data.buffer,0,data.buffer.length);
+ if (readLength == -1)
+ throw new FileStorageRuntimeException("HttpServletRequest 解析失败,尚未发现文件");
+ data.totalReadLength += readLength;
+ if (readLength == data.buffer.length)
+ throw new FileStorageRuntimeException("HttpServletRequest 解析失败,参数超过缓冲区大小");
+ return Arrays.copyOfRange(data.buffer,0,readLength);
+ }
+
+
+ /**
+ * 读取输入流,一次读取一行。从偏移量开始,将字节读入数组,直到读取一定数量的字节或到达换行符,该换行符也会读入数组
+ *
+ * 如果此方法在读取最大字节数之前到达输入流的末尾,则返回 -1
+ *
+ * @param in 输入流
+ * @param b 读取数据的字节数组
+ * @param off 一个整数,指定此方法开始读取的字符
+ * @param len 指定要读取的最大字节数的整数
+ * @return 一个整数,指定实际读取的字节数,如果到达流的末尾,则为 -1
+ * @throws IOException 如果发生输入或输出异常
+ */
+ public static int readLine(InputStream in,byte[] b,int off,int len) throws IOException {
+ if (len <= 0) return 0;
+ int count = 0, c;
+ while ((c = in.read()) != -1) {
+ b[off++] = (byte) c;
+ count++;
+ if (c == '\n' || count == len) break;
+ }
+ return count > 0 ? count : -1;
+ }
+
+ /**
+ * 用于读取 MultipartFormData 中 Part 的内容的 InputStream
+ */
+ public static class MultipartFormDataPartInputStream extends InputStream {
+ private final MultipartFormData data;
+ private int bufferLength = 0;
+ private int index = -1;
+ /**
+ * 状态,0未读取,1读取中,2已读完
+ */
+ private int status = 0;
+
+
+ public MultipartFormDataPartInputStream(MultipartFormData data) {
+ this.data = data;
+ }
+
+ @Override
+ public int read() throws IOException {
+ if (index + 1 == bufferLength) {//当前缓冲区已读完
+ if (status == 2) return -1;
+ readLineBuffer();
+ if (index + 1 == bufferLength && status == 2) return -1;
+ }
+ return data.buffer[++index] & 0xff;
+ }
+
+ protected void readLineBuffer() throws IOException {
+ if (status == 2) return;
+ int readLength = readLine(data.inputStream,data.buffer,0,data.buffer.length);
+ if (readLength == -1)
+ throw new FileStorageRuntimeException("HttpServletRequest 解析失败,文件尚未完整读取");
+
+ data.totalReadLength += readLength;
+ //判断是否为结束行
+ if (isEndLine(data.buffer,readLength)) {
+ status = 2;
+ return;
+ }
+
+ bufferLength = readLength;
+ index = -1;
+
+ //如果当前读取的数据是以换行符结尾的,则判断下一行是否为结束行
+ if (endsWithLineEndFlag(data.buffer,readLength) && nextLineIsEndLine()) {
+ status = 2;
+ bufferLength -= data.boundary.lineEndFlagBytes.length;
+ }
+
+
+ }
+
+ /**
+ * 下一行是结束行
+ */
+ protected boolean nextLineIsEndLine() throws IOException {
+ data.inputStream.mark(data.boundary.endLineBytes.length);
+ byte[] bytes = new byte[data.boundary.endLineBytes.length];
+ int readLength = readLine(data.inputStream,bytes,0,bytes.length);
+ data.inputStream.reset();
+ return isEndLine(bytes,readLength);
+ }
+
+ /**
+ * 是否以行结束符为结尾
+ */
+ protected boolean endsWithLineEndFlag(byte[] buffer,int readLength) {
+ if (readLength < data.boundary.lineEndFlagBytes.length) return false;
+ byte[] bytes = Arrays.copyOfRange(buffer,readLength - data.boundary.lineEndFlagBytes.length,readLength);
+ return Arrays.equals(bytes,data.boundary.lineEndFlagBytes);
+ }
+
+ /**
+ * 是否为 Part 结束行
+ */
+ protected boolean isEndLine(byte[] buffer,int readLength) {
+ if (readLength == data.boundary.lineBytes.length
+ && Arrays.equals(Arrays.copyOfRange(buffer,0,readLength),data.boundary.lineBytes)) {
+ return true;
+ } else return readLength == data.boundary.endLineBytes.length
+ && Arrays.equals(Arrays.copyOfRange(buffer,0,readLength),data.boundary.endLineBytes);
+ }
+ }
+
+ @Getter
+ public static class Boundary {
+ private String boundary;
+ private String line;
+ private byte[] lineBytes;
+ private byte[] endLineBytes;
+ private String endLine;
+ private int footerByteLength;
+ private String lineEndFlag;
+ private byte[] lineEndFlagBytes;
+
+ public static Boundary create(byte[] bytes,String boundary,Charset charset) {
+ String line = new String(bytes,charset);
+ if (!line.contains(boundary)) return null;
+ Boundary instance = new Boundary();
+ instance.boundary = boundary;
+ instance.line = line;
+ instance.lineBytes = bytes;
+
+ instance.lineEndFlag = line.endsWith("\r\n") ? "\r\n" : "\n";
+ instance.lineEndFlagBytes = instance.lineEndFlag.getBytes(charset);
+
+ instance.endLine = line.substring(0,line.length() - instance.lineEndFlag.length()) + "--" + instance.lineEndFlag;
+ instance.endLineBytes = instance.endLine.getBytes(charset);
+ instance.footerByteLength = (instance.endLine + instance.lineEndFlag).getBytes(charset).length;
+ return instance;
+ }
+
+ /**
+ * 从 contentType 中获取 boundary 参数
+ * multipart/form-data; boundary=----WebKitFormBoundary0iQfWrHD6Yl9PNRe
+ */
+ public static String getBoundary(String contentType) {
+ if (contentType == null) return null;
+ int begin = contentType.indexOf("boundary=");
+ if (begin < 0) return null;
+ int end = contentType.indexOf(";",begin);
+ if (end < 0) end = contentType.length();
+ begin += "boundary=".length();
+ return contentType.substring(begin,end).trim();
+ }
+ }
+
+ @Getter
+ public static class MultipartFormData {
+ private InputStream inputStream;
+ private Boundary boundary;
+ private Charset charset;
+ private Long contentLength;
+ private byte[] buffer;
+ private long totalReadLength = 0L;
+ private Map parameterMap;
+ /**
+ * 缩略图字节数组
+ */
+ private byte[] thFileBytes;
+ /**
+ * 缩略图 MIME 类型
+ */
+ private String thFileContentType;
+ /**
+ * 缩略图原始文件名
+ */
+ private String thFileOriginalFilename;
+ /**
+ * 文件的输入流
+ */
+ private InputStream fileInputStream;
+ /**
+ * 文件 MIME 类型
+ */
+ private String fileContentType;
+ /**
+ * 原始文件名
+ */
+ private String fileOriginalFilename;
+ /**
+ * 文件大小
+ */
+ private Long fileSize;
+
+ /**
+ * 获取参数值
+ */
+ public String getParameter(String name) {
+ if (parameterMap == null) return null;
+ String[] values = parameterMap.get(name);
+ if (values == null || values.length == 0) return null;
+ return values[0];
+ }
+
+ /**
+ * 获取多个参数值
+ */
+ public String[] getParameterValues(String name) {
+ if (parameterMap == null) return null;
+ return parameterMap.get(name);
+ }
+ }
+}
diff --git a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/file/UriFileWrapper.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/file/UriFileWrapper.java
similarity index 94%
rename from file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/file/UriFileWrapper.java
rename to x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/file/UriFileWrapper.java
index 1cf531d5..f2a667cb 100644
--- a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/file/UriFileWrapper.java
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/file/UriFileWrapper.java
@@ -1,4 +1,4 @@
-package cn.xuyanwu.spring.file.storage.file;
+package org.dromara.x.file.storage.core.file;
import cn.hutool.core.io.IoUtil;
import lombok.Getter;
diff --git a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/file/UriFileWrapperAdapter.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/file/UriFileWrapperAdapter.java
similarity index 95%
rename from file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/file/UriFileWrapperAdapter.java
rename to x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/file/UriFileWrapperAdapter.java
index 6dc13e9e..19a88610 100644
--- a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/file/UriFileWrapperAdapter.java
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/file/UriFileWrapperAdapter.java
@@ -1,16 +1,16 @@
-package cn.xuyanwu.spring.file.storage.file;
+package org.dromara.x.file.storage.core.file;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.ReUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.URLUtil;
-import cn.xuyanwu.spring.file.storage.tika.ContentTypeDetect;
-import cn.xuyanwu.spring.file.storage.util.Tools;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
+import org.dromara.x.file.storage.core.tika.ContentTypeDetect;
+import org.dromara.x.file.storage.core.util.Tools;
import java.io.IOException;
import java.io.InputStream;
diff --git a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/AliyunOssFileStorage.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/AliyunOssFileStorage.java
similarity index 84%
rename from file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/AliyunOssFileStorage.java
rename to x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/AliyunOssFileStorage.java
index a995b2a7..48ab0aa8 100644
--- a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/AliyunOssFileStorage.java
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/AliyunOssFileStorage.java
@@ -1,18 +1,19 @@
-package cn.xuyanwu.spring.file.storage.platform;
+package org.dromara.x.file.storage.core.platform;
+import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.StrUtil;
-import cn.xuyanwu.spring.file.storage.FileInfo;
-import cn.xuyanwu.spring.file.storage.FileStorageProperties.AliyunOssConfig;
-import cn.xuyanwu.spring.file.storage.ProgressListener;
-import cn.xuyanwu.spring.file.storage.UploadPretreatment;
-import cn.xuyanwu.spring.file.storage.exception.FileStorageRuntimeException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.event.ProgressEventType;
import com.aliyun.oss.model.*;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
+import org.dromara.x.file.storage.core.FileInfo;
+import org.dromara.x.file.storage.core.FileStorageProperties.AliyunOssConfig;
+import org.dromara.x.file.storage.core.ProgressListener;
+import org.dromara.x.file.storage.core.UploadPretreatment;
+import org.dromara.x.file.storage.core.exception.FileStorageRuntimeException;
import java.io.ByteArrayInputStream;
import java.io.IOException;
@@ -77,15 +78,12 @@ public boolean save(FileInfo fileInfo,UploadPretreatment pre) {
String newFileKey = getFileKey(fileInfo);
fileInfo.setUrl(domain + newFileKey);
CannedAccessControlList fileAcl = getAcl(fileInfo.getFileAcl());
+ ObjectMetadata metadata = getObjectMetadata(fileInfo,fileAcl);
ProgressListener listener = pre.getProgressListener();
OSS client = getClient();
boolean useMultipartUpload = fileInfo.getSize() >= multipartThreshold;
String uploadId = null;
try (InputStream in = pre.getFileWrapper().getInputStream()) {
- ObjectMetadata metadata = new ObjectMetadata();
- metadata.setContentLength(fileInfo.getSize());
- metadata.setContentType(fileInfo.getContentType());
- metadata.setObjectAcl(fileAcl);
if (useMultipartUpload) {//分片上传
uploadId = client.initiateMultipartUpload(new InitiateMultipartUploadRequest(bucketName,newFileKey,metadata)).getUploadId();
List partList = new ArrayList<>();
@@ -136,11 +134,7 @@ public boolean save(FileInfo fileInfo,UploadPretreatment pre) {
if (thumbnailBytes != null) { //上传缩略图
String newThFileKey = getThFileKey(fileInfo);
fileInfo.setThUrl(domain + newThFileKey);
- ObjectMetadata thMetadata = new ObjectMetadata();
- thMetadata.setContentLength(thumbnailBytes.length);
- thMetadata.setContentType(fileInfo.getThContentType());
- thMetadata.setObjectAcl(getAcl(fileInfo.getThFileAcl()));
- client.putObject(bucketName,newThFileKey,new ByteArrayInputStream(thumbnailBytes),thMetadata);
+ client.putObject(bucketName,newThFileKey,new ByteArrayInputStream(thumbnailBytes),getThObjectMetadata(fileInfo));
}
return true;
} catch (IOException e) {
@@ -173,6 +167,36 @@ public CannedAccessControlList getAcl(Object acl) {
}
}
+ /**
+ * 获取对象的元数据
+ */
+ public ObjectMetadata getObjectMetadata(FileInfo fileInfo,CannedAccessControlList fileAcl) {
+ ObjectMetadata metadata = new ObjectMetadata();
+ metadata.setContentLength(fileInfo.getSize());
+ metadata.setContentType(fileInfo.getContentType());
+ metadata.setObjectAcl(fileAcl);
+ metadata.setUserMetadata(fileInfo.getUserMetadata());
+ if (CollUtil.isNotEmpty(fileInfo.getMetadata())) {
+ fileInfo.getMetadata().forEach(metadata::setHeader);
+ }
+ return metadata;
+ }
+
+ /**
+ * 获取缩略图对象的元数据
+ */
+ public ObjectMetadata getThObjectMetadata(FileInfo fileInfo) {
+ ObjectMetadata metadata = new ObjectMetadata();
+ metadata.setContentLength(fileInfo.getThSize());
+ metadata.setContentType(fileInfo.getThContentType());
+ metadata.setObjectAcl(getAcl(fileInfo.getThFileAcl()));
+ metadata.setUserMetadata(fileInfo.getThUserMetadata());
+ if (CollUtil.isNotEmpty(fileInfo.getThMetadata())) {
+ fileInfo.getThMetadata().forEach(metadata::setHeader);
+ }
+ return metadata;
+ }
+
@Override
public boolean isSupportPresignedUrl() {
@@ -214,6 +238,11 @@ public boolean setThFileAcl(FileInfo fileInfo,Object acl) {
return true;
}
+ @Override
+ public boolean isSupportMetadata() {
+ return true;
+ }
+
@Override
public boolean delete(FileInfo fileInfo) {
OSS client = getClient();
diff --git a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/AliyunOssFileStorageClientFactory.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/AliyunOssFileStorageClientFactory.java
similarity index 90%
rename from file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/AliyunOssFileStorageClientFactory.java
rename to x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/AliyunOssFileStorageClientFactory.java
index ea0990d6..01552406 100644
--- a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/AliyunOssFileStorageClientFactory.java
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/AliyunOssFileStorageClientFactory.java
@@ -1,11 +1,11 @@
-package cn.xuyanwu.spring.file.storage.platform;
+package org.dromara.x.file.storage.core.platform;
-import cn.xuyanwu.spring.file.storage.FileStorageProperties.AliyunOssConfig;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
+import org.dromara.x.file.storage.core.FileStorageProperties.AliyunOssConfig;
/**
* 阿里云 OSS 存储平台的 Client 工厂
diff --git a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/AmazonS3FileStorage.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/AmazonS3FileStorage.java
similarity index 84%
rename from file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/AmazonS3FileStorage.java
rename to x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/AmazonS3FileStorage.java
index 7956dcfc..7b808c75 100644
--- a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/AmazonS3FileStorage.java
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/AmazonS3FileStorage.java
@@ -1,19 +1,22 @@
-package cn.xuyanwu.spring.file.storage.platform;
+package org.dromara.x.file.storage.core.platform;
+import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.StrUtil;
-import cn.xuyanwu.spring.file.storage.FileInfo;
-import cn.xuyanwu.spring.file.storage.FileStorageProperties;
-import cn.xuyanwu.spring.file.storage.ProgressListener;
-import cn.xuyanwu.spring.file.storage.UploadPretreatment;
-import cn.xuyanwu.spring.file.storage.exception.FileStorageRuntimeException;
+import com.amazonaws.RequestClientOptions;
import com.amazonaws.event.ProgressEventType;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.model.*;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
+import org.dromara.x.file.storage.core.FileInfo;
+import org.dromara.x.file.storage.core.FileStorageProperties;
+import org.dromara.x.file.storage.core.ProgressListener;
+import org.dromara.x.file.storage.core.UploadPretreatment;
+import org.dromara.x.file.storage.core.exception.FileStorageRuntimeException;
+import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
@@ -76,14 +79,12 @@ public boolean save(FileInfo fileInfo,UploadPretreatment pre) {
String newFileKey = getFileKey(fileInfo);
fileInfo.setUrl(domain + newFileKey);
CannedAccessControlList fileAcl = getAcl(fileInfo.getFileAcl());
+ ObjectMetadata metadata = getObjectMetadata(fileInfo);
ProgressListener listener = pre.getProgressListener();
AmazonS3 client = getClient();
boolean useMultipartUpload = fileInfo.getSize() >= multipartThreshold;
String uploadId = null;
try (InputStream in = pre.getFileWrapper().getInputStream()) {
- ObjectMetadata metadata = new ObjectMetadata();
- metadata.setContentLength(fileInfo.getSize());
- metadata.setContentType(fileInfo.getContentType());
if (useMultipartUpload) {//分片上传
uploadId = client.initiateMultipartUpload(new InitiateMultipartUploadRequest(bucketName,newFileKey,metadata)).getUploadId();
List partList = new ArrayList<>();
@@ -113,7 +114,8 @@ public boolean save(FileInfo fileInfo,UploadPretreatment pre) {
if (fileAcl != null) client.setObjectAcl(bucketName,newFileKey,fileAcl);
if (listener != null) listener.finish();
} else {
- PutObjectRequest request = new PutObjectRequest(bucketName,newFileKey,in,metadata);
+ BufferedInputStream bin = new BufferedInputStream(in,RequestClientOptions.DEFAULT_STREAM_BUFFER_SIZE);
+ PutObjectRequest request = new PutObjectRequest(bucketName,newFileKey,bin,metadata);
request.setCannedAcl(fileAcl);
if (listener != null) {
AtomicLong progressSize = new AtomicLong();
@@ -134,10 +136,7 @@ public boolean save(FileInfo fileInfo,UploadPretreatment pre) {
if (thumbnailBytes != null) { //上传缩略图
String newThFileKey = getThFileKey(fileInfo);
fileInfo.setThUrl(domain + newThFileKey);
- ObjectMetadata thMetadata = new ObjectMetadata();
- thMetadata.setContentLength(thumbnailBytes.length);
- thMetadata.setContentType(fileInfo.getThContentType());
- PutObjectRequest request = new PutObjectRequest(bucketName,newThFileKey,new ByteArrayInputStream(thumbnailBytes),thMetadata);
+ PutObjectRequest request = new PutObjectRequest(bucketName,newThFileKey,new ByteArrayInputStream(thumbnailBytes),getThObjectMetadata(fileInfo));
request.setCannedAcl(getAcl(fileInfo.getThFileAcl()));
client.putObject(request);
}
@@ -173,6 +172,34 @@ public CannedAccessControlList getAcl(Object acl) {
}
}
+ /**
+ * 获取对象的元数据
+ */
+ public ObjectMetadata getObjectMetadata(FileInfo fileInfo) {
+ ObjectMetadata metadata = new ObjectMetadata();
+ metadata.setContentLength(fileInfo.getSize());
+ metadata.setContentType(fileInfo.getContentType());
+ metadata.setUserMetadata(fileInfo.getUserMetadata());
+ if (CollUtil.isNotEmpty(fileInfo.getMetadata())) {
+ fileInfo.getMetadata().forEach(metadata::setHeader);
+ }
+ return metadata;
+ }
+
+ /**
+ * 获取缩略图对象的元数据
+ */
+ public ObjectMetadata getThObjectMetadata(FileInfo fileInfo) {
+ ObjectMetadata metadata = new ObjectMetadata();
+ metadata.setContentLength(fileInfo.getThSize());
+ metadata.setContentType(fileInfo.getThContentType());
+ metadata.setUserMetadata(fileInfo.getThUserMetadata());
+ if (CollUtil.isNotEmpty(fileInfo.getThMetadata())) {
+ fileInfo.getThMetadata().forEach(metadata::setHeader);
+ }
+ return metadata;
+ }
+
@Override
public boolean isSupportPresignedUrl() {
return true;
@@ -213,6 +240,11 @@ public boolean setThFileAcl(FileInfo fileInfo,Object acl) {
return true;
}
+ @Override
+ public boolean isSupportMetadata() {
+ return true;
+ }
+
@Override
public boolean delete(FileInfo fileInfo) {
AmazonS3 client = getClient();
diff --git a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/AmazonS3FileStorageClientFactory.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/AmazonS3FileStorageClientFactory.java
similarity index 93%
rename from file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/AmazonS3FileStorageClientFactory.java
rename to x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/AmazonS3FileStorageClientFactory.java
index 35b06415..93d9a446 100644
--- a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/AmazonS3FileStorageClientFactory.java
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/AmazonS3FileStorageClientFactory.java
@@ -1,7 +1,6 @@
-package cn.xuyanwu.spring.file.storage.platform;
+package org.dromara.x.file.storage.core.platform;
import cn.hutool.core.util.StrUtil;
-import cn.xuyanwu.spring.file.storage.FileStorageProperties.AmazonS3Config;
import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.client.builder.AwsClientBuilder;
@@ -10,6 +9,7 @@
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
+import org.dromara.x.file.storage.core.FileStorageProperties.AmazonS3Config;
/**
* Amazon S3 存储平台的 Client 工厂
diff --git a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/BaiduBosFileStorage.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/BaiduBosFileStorage.java
similarity index 80%
rename from file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/BaiduBosFileStorage.java
rename to x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/BaiduBosFileStorage.java
index d4ee500c..16626880 100644
--- a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/BaiduBosFileStorage.java
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/BaiduBosFileStorage.java
@@ -1,18 +1,23 @@
-package cn.xuyanwu.spring.file.storage.platform;
+package org.dromara.x.file.storage.core.platform;
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.bean.copier.CopyOptions;
+import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.IoUtil;
+import cn.hutool.core.text.NamingCase;
+import cn.hutool.core.util.CharUtil;
import cn.hutool.core.util.StrUtil;
-import cn.xuyanwu.spring.file.storage.FileInfo;
-import cn.xuyanwu.spring.file.storage.FileStorageProperties.BaiduBosConfig;
-import cn.xuyanwu.spring.file.storage.ProgressListener;
-import cn.xuyanwu.spring.file.storage.UploadPretreatment;
-import cn.xuyanwu.spring.file.storage.exception.FileStorageRuntimeException;
import com.baidubce.BceServiceException;
import com.baidubce.services.bos.BosClient;
import com.baidubce.services.bos.model.*;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
+import org.dromara.x.file.storage.core.FileInfo;
+import org.dromara.x.file.storage.core.FileStorageProperties.BaiduBosConfig;
+import org.dromara.x.file.storage.core.ProgressListener;
+import org.dromara.x.file.storage.core.UploadPretreatment;
+import org.dromara.x.file.storage.core.exception.FileStorageRuntimeException;
import java.io.ByteArrayInputStream;
import java.io.IOException;
@@ -74,17 +79,12 @@ public boolean save(FileInfo fileInfo,UploadPretreatment pre) {
fileInfo.setBasePath(basePath);
String newFileKey = getFileKey(fileInfo);
fileInfo.setUrl(domain + newFileKey);
- CannedAccessControlList fileAcl = getAcl(fileInfo.getFileAcl());
+ ObjectMetadata metadata = getObjectMetadata(fileInfo);
ProgressListener listener = pre.getProgressListener();
BosClient client = getClient();
boolean useMultipartUpload = fileInfo.getSize() >= multipartThreshold;
String uploadId = null;
try (InputStream in = pre.getFileWrapper().getInputStream()) {
- ObjectMetadata metadata = new ObjectMetadata();
- metadata.setContentLength(fileInfo.getSize());
- metadata.setContentType(fileInfo.getContentType());
- if (fileAcl != null) metadata.setxBceAcl(fileAcl.toString());
-
if (useMultipartUpload) {//分片上传
InitiateMultipartUploadRequest initiateMultipartUploadRequest = new InitiateMultipartUploadRequest(bucketName,newFileKey);
initiateMultipartUploadRequest.setObjectMetadata(metadata);
@@ -134,12 +134,8 @@ public void onProgress(long currentSize,long totalSize,Object data) {
if (thumbnailBytes != null) { //上传缩略图
String newThFileKey = getThFileKey(fileInfo);
fileInfo.setThUrl(domain + newThFileKey);
- ObjectMetadata thMetadata = new ObjectMetadata();
- thMetadata.setContentLength(thumbnailBytes.length);
- thMetadata.setContentType(fileInfo.getThContentType());
- CannedAccessControlList thFileAcl = getAcl(fileInfo.getThFileAcl());
- if (thFileAcl != null) thMetadata.setxBceAcl(thFileAcl.toString());
- client.putObject(bucketName,newThFileKey,new ByteArrayInputStream(thumbnailBytes),thMetadata);
+
+ client.putObject(bucketName,newThFileKey,new ByteArrayInputStream(thumbnailBytes),getThObjectMetadata(fileInfo));
}
return true;
@@ -171,6 +167,41 @@ public CannedAccessControlList getAcl(Object acl) {
return null;
}
+
+ /**
+ * 获取对象的元数据
+ */
+ public ObjectMetadata getObjectMetadata(FileInfo fileInfo) {
+ CannedAccessControlList fileAcl = getAcl(fileInfo.getFileAcl());
+ ObjectMetadata metadata = new ObjectMetadata();
+ metadata.setContentLength(fileInfo.getSize());
+ metadata.setContentType(fileInfo.getContentType());
+ if (fileAcl != null) metadata.setxBceAcl(fileAcl.toString());
+ metadata.setUserMetadata(fileInfo.getUserMetadata());
+ if (CollUtil.isNotEmpty(fileInfo.getMetadata())) {
+ CopyOptions copyOptions = CopyOptions.create().ignoreCase().setFieldNameEditor(name -> NamingCase.toCamelCase(name,CharUtil.DASHED));
+ BeanUtil.copyProperties(fileInfo.getMetadata(),metadata,copyOptions);
+ }
+ return metadata;
+ }
+
+ /**
+ * 获取缩略图对象的元数据
+ */
+ public ObjectMetadata getThObjectMetadata(FileInfo fileInfo) {
+ ObjectMetadata metadata = new ObjectMetadata();
+ metadata.setContentLength(fileInfo.getThSize());
+ metadata.setContentType(fileInfo.getThContentType());
+ CannedAccessControlList thFileAcl = getAcl(fileInfo.getThFileAcl());
+ if (thFileAcl != null) metadata.setxBceAcl(thFileAcl.toString());
+ metadata.setUserMetadata(fileInfo.getThUserMetadata());
+ if (CollUtil.isNotEmpty(fileInfo.getThMetadata())) {
+ CopyOptions copyOptions = CopyOptions.create().ignoreCase().setFieldNameEditor(name -> NamingCase.toCamelCase(name,CharUtil.DASHED));
+ BeanUtil.copyProperties(fileInfo.getThMetadata(),metadata,copyOptions);
+ }
+ return metadata;
+ }
+
@Override
public boolean isSupportPresignedUrl() {
return true;
@@ -213,6 +244,11 @@ public boolean setThFileAcl(FileInfo fileInfo,Object acl) {
return true;
}
+ @Override
+ public boolean isSupportMetadata() {
+ return true;
+ }
+
@Override
public boolean delete(FileInfo fileInfo) {
diff --git a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/BaiduBosFileStorageClientFactory.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/BaiduBosFileStorageClientFactory.java
similarity index 93%
rename from file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/BaiduBosFileStorageClientFactory.java
rename to x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/BaiduBosFileStorageClientFactory.java
index 8a09ffbe..a2606b12 100644
--- a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/BaiduBosFileStorageClientFactory.java
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/BaiduBosFileStorageClientFactory.java
@@ -1,7 +1,6 @@
-package cn.xuyanwu.spring.file.storage.platform;
+package org.dromara.x.file.storage.core.platform;
import cn.hutool.core.util.StrUtil;
-import cn.xuyanwu.spring.file.storage.FileStorageProperties.BaiduBosConfig;
import com.baidubce.Protocol;
import com.baidubce.auth.DefaultBceCredentials;
import com.baidubce.services.bos.BosClient;
@@ -9,6 +8,7 @@
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
+import org.dromara.x.file.storage.core.FileStorageProperties.BaiduBosConfig;
/**
* 百度云 BOS 存储平台的 Client 工厂
diff --git a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/FileStorage.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/FileStorage.java
similarity index 86%
rename from file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/FileStorage.java
rename to x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/FileStorage.java
index 4d0b6945..ce93caaf 100644
--- a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/FileStorage.java
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/FileStorage.java
@@ -1,7 +1,7 @@
-package cn.xuyanwu.spring.file.storage.platform;
+package org.dromara.x.file.storage.core.platform;
-import cn.xuyanwu.spring.file.storage.FileInfo;
-import cn.xuyanwu.spring.file.storage.UploadPretreatment;
+import org.dromara.x.file.storage.core.FileInfo;
+import org.dromara.x.file.storage.core.UploadPretreatment;
import java.io.InputStream;
import java.util.Date;
@@ -73,6 +73,13 @@ default boolean setThFileAcl(FileInfo fileInfo,Object acl) {
return false;
}
+ /**
+ * 是否支持 Metadata,一般情况下只有对象存储支持该功能
+ */
+ default boolean isSupportMetadata() {
+ return false;
+ }
+
/**
* 删除文件
*/
diff --git a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/FileStorageClientFactory.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/FileStorageClientFactory.java
similarity index 91%
rename from file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/FileStorageClientFactory.java
rename to x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/FileStorageClientFactory.java
index d0d99430..3c5afb14 100644
--- a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/FileStorageClientFactory.java
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/FileStorageClientFactory.java
@@ -1,4 +1,4 @@
-package cn.xuyanwu.spring.file.storage.platform;
+package org.dromara.x.file.storage.core.platform;
/**
* 存储平台的 Client 的对象的工厂接口
diff --git a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/FtpFileStorage.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/FtpFileStorage.java
similarity index 88%
rename from file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/FtpFileStorage.java
rename to x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/FtpFileStorage.java
index c4cff2d6..962196be 100644
--- a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/FtpFileStorage.java
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/FtpFileStorage.java
@@ -1,18 +1,19 @@
-package cn.xuyanwu.spring.file.storage.platform;
+package org.dromara.x.file.storage.core.platform;
+import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.ftp.Ftp;
-import cn.xuyanwu.spring.file.storage.FileInfo;
-import cn.xuyanwu.spring.file.storage.FileStorageProperties.FtpConfig;
-import cn.xuyanwu.spring.file.storage.ProgressInputStream;
-import cn.xuyanwu.spring.file.storage.ProgressListener;
-import cn.xuyanwu.spring.file.storage.UploadPretreatment;
-import cn.xuyanwu.spring.file.storage.exception.FileStorageRuntimeException;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.apache.commons.net.ftp.FTPClient;
+import org.dromara.x.file.storage.core.FileInfo;
+import org.dromara.x.file.storage.core.FileStorageProperties.FtpConfig;
+import org.dromara.x.file.storage.core.ProgressInputStream;
+import org.dromara.x.file.storage.core.ProgressListener;
+import org.dromara.x.file.storage.core.UploadPretreatment;
+import org.dromara.x.file.storage.core.exception.FileStorageRuntimeException;
import java.io.ByteArrayInputStream;
import java.io.IOException;
@@ -80,9 +81,12 @@ public boolean save(FileInfo fileInfo,UploadPretreatment pre) {
fileInfo.setBasePath(basePath);
String newFileKey = getFileKey(fileInfo);
fileInfo.setUrl(domain + newFileKey);
- if (fileInfo.getFileAcl() != null) {
+ if (fileInfo.getFileAcl() != null && pre.getNotSupportAclThrowException()) {
throw new FileStorageRuntimeException("文件上传失败,FTP 不支持设置 ACL!platform:" + platform + ",filename:" + fileInfo.getOriginalFilename());
}
+ if (CollUtil.isNotEmpty(fileInfo.getUserMetadata()) && pre.getNotSupportMetadataThrowException()) {
+ throw new FileStorageRuntimeException("文件上传失败,FTP 不支持设置 UserMetadata!platform:" + platform + ",filename:" + fileInfo.getOriginalFilename());
+ }
ProgressListener listener = pre.getProgressListener();
Ftp client = getClient();
diff --git a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/FtpFileStorageClientFactory.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/FtpFileStorageClientFactory.java
similarity index 95%
rename from file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/FtpFileStorageClientFactory.java
rename to x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/FtpFileStorageClientFactory.java
index a71db8fa..237b4c6a 100644
--- a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/FtpFileStorageClientFactory.java
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/FtpFileStorageClientFactory.java
@@ -1,11 +1,9 @@
-package cn.xuyanwu.spring.file.storage.platform;
+package org.dromara.x.file.storage.core.platform;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.ftp.Ftp;
import cn.hutool.extra.ftp.FtpException;
import cn.hutool.extra.ftp.FtpMode;
-import cn.xuyanwu.spring.file.storage.FileStorageProperties.FtpConfig;
-import cn.xuyanwu.spring.file.storage.exception.FileStorageRuntimeException;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
@@ -16,6 +14,8 @@
import org.apache.commons.pool2.impl.DefaultPooledObject;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
+import org.dromara.x.file.storage.core.FileStorageProperties.FtpConfig;
+import org.dromara.x.file.storage.core.exception.FileStorageRuntimeException;
import java.nio.charset.Charset;
diff --git a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/GoogleCloudStorageFileStorage.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/GoogleCloudStorageFileStorage.java
similarity index 76%
rename from file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/GoogleCloudStorageFileStorage.java
rename to x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/GoogleCloudStorageFileStorage.java
index 01d03643..9278b45c 100644
--- a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/GoogleCloudStorageFileStorage.java
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/GoogleCloudStorageFileStorage.java
@@ -1,12 +1,11 @@
-package cn.xuyanwu.spring.file.storage.platform;
+package org.dromara.x.file.storage.core.platform;
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.bean.copier.CopyOptions;
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.text.NamingCase;
+import cn.hutool.core.util.CharUtil;
import cn.hutool.core.util.StrUtil;
-import cn.xuyanwu.spring.file.storage.FileInfo;
-import cn.xuyanwu.spring.file.storage.FileStorageProperties.GoogleCloudStorageConfig;
-import cn.xuyanwu.spring.file.storage.ProgressInputStream;
-import cn.xuyanwu.spring.file.storage.ProgressListener;
-import cn.xuyanwu.spring.file.storage.UploadPretreatment;
-import cn.xuyanwu.spring.file.storage.exception.FileStorageRuntimeException;
import com.google.cloud.ReadChannel;
import com.google.cloud.storage.*;
import com.google.cloud.storage.Storage.PredefinedAcl;
@@ -14,6 +13,12 @@
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
+import org.dromara.x.file.storage.core.FileInfo;
+import org.dromara.x.file.storage.core.FileStorageProperties.GoogleCloudStorageConfig;
+import org.dromara.x.file.storage.core.ProgressInputStream;
+import org.dromara.x.file.storage.core.ProgressListener;
+import org.dromara.x.file.storage.core.UploadPretreatment;
+import org.dromara.x.file.storage.core.exception.FileStorageRuntimeException;
import java.io.ByteArrayInputStream;
import java.io.IOException;
@@ -26,6 +31,7 @@
/**
* GoogleCloud Storage 存储
+ *
* @author Kytrun Xuyanwu
* @version 1.0
* {@code @date} 2022/11/4 9:56
@@ -76,22 +82,14 @@ public boolean save(FileInfo fileInfo,UploadPretreatment pre) {
fileInfo.setBasePath(basePath);
String newFileKey = getFileKey(fileInfo);
fileInfo.setUrl(domain + newFileKey);
- AclWrapper fileAcl = getAcl(fileInfo.getFileAcl());
+ ArrayList optionList = new ArrayList<>();
+ BlobInfo.Builder blobInfoBuilder = BlobInfo.newBuilder(bucketName,newFileKey);
+ setMetadata(blobInfoBuilder,fileInfo,optionList);
ProgressListener listener = pre.getProgressListener();
Storage client = getClient();
try (InputStream in = pre.getFileWrapper().getInputStream()) {
// 上传原文件
- ArrayList optionList = new ArrayList<>();
- BlobInfo.Builder blobInfoBuilder = BlobInfo.newBuilder(bucketName,newFileKey).setContentType(fileInfo.getContentType());
- if (fileAcl != null) {
- if (fileAcl.getAclList() != null) {
- blobInfoBuilder.setAcl(fileAcl.getAclList());
- } else if (fileAcl.getPredefinedAcl() != null) {
- optionList.add(Storage.BlobWriteOption.predefinedAcl(fileAcl.getPredefinedAcl()));
- }
- }
-
client.createFrom(blobInfoBuilder.build(),
listener == null ? in : new ProgressInputStream(in,listener,fileInfo.getSize()),
optionList.toArray(new Storage.BlobWriteOption[]{})
@@ -103,15 +101,8 @@ public boolean save(FileInfo fileInfo,UploadPretreatment pre) {
String newThFileKey = getThFileKey(fileInfo);
fileInfo.setThUrl(domain + newThFileKey);
ArrayList thOptionList = new ArrayList<>();
- BlobInfo.Builder thBlobInfoBuilder = BlobInfo.newBuilder(bucketName,newThFileKey).setContentType(fileInfo.getThContentType());
- AclWrapper thFileAcl = getAcl(fileInfo.getThFileAcl());
- if (thFileAcl != null) {
- if (thFileAcl.getAclList() != null) {
- thBlobInfoBuilder.setAcl(thFileAcl.getAclList());
- } else if (thFileAcl.getPredefinedAcl() != null) {
- thOptionList.add(Storage.BlobWriteOption.predefinedAcl(thFileAcl.getPredefinedAcl()));
- }
- }
+ BlobInfo.Builder thBlobInfoBuilder = BlobInfo.newBuilder(bucketName,newThFileKey);
+ setThMetadata(thBlobInfoBuilder,fileInfo,thOptionList);
client.createFrom(thBlobInfoBuilder.build(),new ByteArrayInputStream(thumbnailBytes),thOptionList.toArray(new Storage.BlobWriteOption[]{}));
}
return true;
@@ -154,6 +145,44 @@ public AclWrapper getAcl(Object acl) {
}
}
+ /**
+ * 设置对象的元数据
+ */
+ public void setMetadata(BlobInfo.Builder blobInfoBuilder,FileInfo fileInfo,ArrayList optionList) {
+ blobInfoBuilder.setContentType(fileInfo.getContentType()).setMetadata(fileInfo.getUserMetadata());
+ if (CollUtil.isNotEmpty(fileInfo.getMetadata())) {
+ CopyOptions copyOptions = CopyOptions.create().ignoreCase().setFieldNameEditor(name -> NamingCase.toCamelCase(name,CharUtil.DASHED));
+ BeanUtil.copyProperties(fileInfo.getMetadata(),blobInfoBuilder,copyOptions);
+ }
+ AclWrapper fileAcl = getAcl(fileInfo.getFileAcl());
+ if (fileAcl != null) {
+ if (fileAcl.getAclList() != null) {
+ blobInfoBuilder.setAcl(fileAcl.getAclList());
+ } else if (fileAcl.getPredefinedAcl() != null) {
+ optionList.add(Storage.BlobWriteOption.predefinedAcl(fileAcl.getPredefinedAcl()));
+ }
+ }
+ }
+
+ /**
+ * 设置缩略图对象的元数据
+ */
+ public void setThMetadata(BlobInfo.Builder blobInfoBuilder,FileInfo fileInfo,ArrayList optionList) {
+ blobInfoBuilder.setContentType(fileInfo.getThContentType()).setMetadata(fileInfo.getThUserMetadata());
+ if (CollUtil.isNotEmpty(fileInfo.getThMetadata())) {
+ CopyOptions copyOptions = CopyOptions.create().ignoreCase().setFieldNameEditor(name -> NamingCase.toCamelCase(name,CharUtil.DASHED));
+ BeanUtil.copyProperties(fileInfo.getThMetadata(),blobInfoBuilder,copyOptions);
+ }
+ AclWrapper fileAcl = getAcl(fileInfo.getThFileAcl());
+ if (fileAcl != null) {
+ if (fileAcl.getAclList() != null) {
+ blobInfoBuilder.setAcl(fileAcl.getAclList());
+ } else if (fileAcl.getPredefinedAcl() != null) {
+ optionList.add(Storage.BlobWriteOption.predefinedAcl(fileAcl.getPredefinedAcl()));
+ }
+ }
+ }
+
@Override
public boolean isSupportAcl() {
return true;
@@ -210,6 +239,11 @@ public String generateThPresignedUrl(FileInfo fileInfo,Date expiration) {
return getClient().signUrl(blobInfo,duration,TimeUnit.MILLISECONDS).toString();
}
+ @Override
+ public boolean isSupportMetadata() {
+ return true;
+ }
+
/**
* 检查并删除对象
* Source Example
diff --git a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/GoogleCloudStorageFileStorageClientFactory.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/GoogleCloudStorageFileStorageClientFactory.java
similarity index 91%
rename from file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/GoogleCloudStorageFileStorageClientFactory.java
rename to x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/GoogleCloudStorageFileStorageClientFactory.java
index 8cddcb4f..a5e2d347 100644
--- a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/GoogleCloudStorageFileStorageClientFactory.java
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/GoogleCloudStorageFileStorageClientFactory.java
@@ -1,14 +1,14 @@
-package cn.xuyanwu.spring.file.storage.platform;
+package org.dromara.x.file.storage.core.platform;
import cn.hutool.core.util.URLUtil;
-import cn.xuyanwu.spring.file.storage.FileStorageProperties.GoogleCloudStorageConfig;
-import cn.xuyanwu.spring.file.storage.exception.FileStorageRuntimeException;
import com.google.auth.oauth2.ServiceAccountCredentials;
import com.google.cloud.storage.Storage;
import com.google.cloud.storage.StorageOptions;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
+import org.dromara.x.file.storage.core.FileStorageProperties.GoogleCloudStorageConfig;
+import org.dromara.x.file.storage.core.exception.FileStorageRuntimeException;
import java.io.IOException;
import java.io.InputStream;
diff --git a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/HuaweiObsFileStorage.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/HuaweiObsFileStorage.java
similarity index 82%
rename from file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/HuaweiObsFileStorage.java
rename to x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/HuaweiObsFileStorage.java
index dc828e2e..ca7df9d9 100644
--- a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/HuaweiObsFileStorage.java
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/HuaweiObsFileStorage.java
@@ -1,18 +1,23 @@
-package cn.xuyanwu.spring.file.storage.platform;
+package org.dromara.x.file.storage.core.platform;
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.bean.copier.CopyOptions;
+import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.IoUtil;
+import cn.hutool.core.text.NamingCase;
+import cn.hutool.core.util.CharUtil;
import cn.hutool.core.util.StrUtil;
-import cn.xuyanwu.spring.file.storage.FileInfo;
-import cn.xuyanwu.spring.file.storage.FileStorageProperties.HuaweiObsConfig;
-import cn.xuyanwu.spring.file.storage.ProgressListener;
-import cn.xuyanwu.spring.file.storage.UploadPretreatment;
-import cn.xuyanwu.spring.file.storage.exception.FileStorageRuntimeException;
import com.obs.services.ObsClient;
import com.obs.services.internal.ObsConvertor;
import com.obs.services.model.*;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
+import org.dromara.x.file.storage.core.FileInfo;
+import org.dromara.x.file.storage.core.FileStorageProperties.HuaweiObsConfig;
+import org.dromara.x.file.storage.core.ProgressListener;
+import org.dromara.x.file.storage.core.UploadPretreatment;
+import org.dromara.x.file.storage.core.exception.FileStorageRuntimeException;
import java.io.ByteArrayInputStream;
import java.io.IOException;
@@ -75,14 +80,12 @@ public boolean save(FileInfo fileInfo,UploadPretreatment pre) {
String newFileKey = getFileKey(fileInfo);
fileInfo.setUrl(domain + newFileKey);
AccessControlList fileAcl = getAcl(fileInfo.getFileAcl());
+ ObjectMetadata metadata = getObjectMetadata(fileInfo);
ProgressListener listener = pre.getProgressListener();
ObsClient client = getClient();
boolean useMultipartUpload = fileInfo.getSize() >= multipartThreshold;
String uploadId = null;
try (InputStream in = pre.getFileWrapper().getInputStream()) {
- ObjectMetadata metadata = new ObjectMetadata();
- metadata.setContentLength(fileInfo.getSize());
- metadata.setContentType(fileInfo.getContentType());
if (useMultipartUpload) {//分片上传
InitiateMultipartUploadRequest initiateMultipartUploadRequest = new InitiateMultipartUploadRequest(bucketName,newFileKey);
initiateMultipartUploadRequest.setMetadata(metadata);
@@ -128,11 +131,8 @@ public boolean save(FileInfo fileInfo,UploadPretreatment pre) {
if (thumbnailBytes != null) { //上传缩略图
String newThFileKey = getThFileKey(fileInfo);
fileInfo.setThUrl(domain + newThFileKey);
- ObjectMetadata thMetadata = new ObjectMetadata();
- thMetadata.setContentLength((long) thumbnailBytes.length);
- thMetadata.setContentType(fileInfo.getThContentType());
PutObjectRequest request = new PutObjectRequest(bucketName,newThFileKey,new ByteArrayInputStream(thumbnailBytes));
- request.setMetadata(thMetadata);
+ request.setMetadata(getThObjectMetadata(fileInfo));
request.setAcl(getAcl(fileInfo.getThFileAcl()));
client.putObject(request);
}
@@ -164,6 +164,36 @@ public AccessControlList getAcl(Object acl) {
}
}
+ /**
+ * 获取对象的元数据
+ */
+ public ObjectMetadata getObjectMetadata(FileInfo fileInfo) {
+ ObjectMetadata metadata = new ObjectMetadata();
+ metadata.setContentLength(fileInfo.getSize());
+ metadata.setContentType(fileInfo.getContentType());
+ fileInfo.getUserMetadata().forEach(metadata::addUserMetadata);
+ if (CollUtil.isNotEmpty(fileInfo.getMetadata())) {
+ CopyOptions copyOptions = CopyOptions.create().ignoreCase().setFieldNameEditor(name -> NamingCase.toCamelCase(name,CharUtil.DASHED));
+ BeanUtil.copyProperties(fileInfo.getMetadata(),metadata,copyOptions);
+ }
+ return metadata;
+ }
+
+ /**
+ * 获取缩略图对象的元数据
+ */
+ public ObjectMetadata getThObjectMetadata(FileInfo fileInfo) {
+ ObjectMetadata metadata = new ObjectMetadata();
+ metadata.setContentLength(fileInfo.getThSize());
+ metadata.setContentType(fileInfo.getThContentType());
+ fileInfo.getThUserMetadata().forEach(metadata::addUserMetadata);
+ if (CollUtil.isNotEmpty(fileInfo.getThMetadata())) {
+ CopyOptions copyOptions = CopyOptions.create().ignoreCase().setFieldNameEditor(name -> NamingCase.toCamelCase(name,CharUtil.DASHED));
+ BeanUtil.copyProperties(fileInfo.getThMetadata(),metadata,copyOptions);
+ }
+ return metadata;
+ }
+
@Override
public boolean isSupportPresignedUrl() {
return true;
@@ -212,6 +242,11 @@ public boolean setThFileAcl(FileInfo fileInfo,Object acl) {
return true;
}
+ @Override
+ public boolean isSupportMetadata() {
+ return true;
+ }
+
@Override
public boolean delete(FileInfo fileInfo) {
ObsClient client = getClient();
diff --git a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/HuaweiObsFileStorageClientFactory.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/HuaweiObsFileStorageClientFactory.java
similarity index 89%
rename from file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/HuaweiObsFileStorageClientFactory.java
rename to x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/HuaweiObsFileStorageClientFactory.java
index eb7d2708..8b0b4752 100644
--- a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/HuaweiObsFileStorageClientFactory.java
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/HuaweiObsFileStorageClientFactory.java
@@ -1,11 +1,11 @@
-package cn.xuyanwu.spring.file.storage.platform;
+package org.dromara.x.file.storage.core.platform;
import cn.hutool.core.io.IoUtil;
-import cn.xuyanwu.spring.file.storage.FileStorageProperties.HuaweiObsConfig;
import com.obs.services.ObsClient;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
+import org.dromara.x.file.storage.core.FileStorageProperties.HuaweiObsConfig;
/**
* 华为云 ObsClient 存储平台的 Client 工厂
diff --git a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/LocalFileStorage.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/LocalFileStorage.java
similarity index 82%
rename from file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/LocalFileStorage.java
rename to x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/LocalFileStorage.java
index 3e7d54bd..603aca7b 100644
--- a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/LocalFileStorage.java
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/LocalFileStorage.java
@@ -1,17 +1,18 @@
-package cn.xuyanwu.spring.file.storage.platform;
+package org.dromara.x.file.storage.core.platform;
+import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
-import cn.xuyanwu.spring.file.storage.FileInfo;
-import cn.xuyanwu.spring.file.storage.FileStorageProperties.LocalConfig;
-import cn.xuyanwu.spring.file.storage.ProgressInputStream;
-import cn.xuyanwu.spring.file.storage.ProgressListener;
-import cn.xuyanwu.spring.file.storage.UploadPretreatment;
-import cn.xuyanwu.spring.file.storage.exception.FileStorageRuntimeException;
-import cn.xuyanwu.spring.file.storage.file.FileWrapper;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
+import org.dromara.x.file.storage.core.FileInfo;
+import org.dromara.x.file.storage.core.FileStorageProperties.LocalConfig;
+import org.dromara.x.file.storage.core.ProgressInputStream;
+import org.dromara.x.file.storage.core.ProgressListener;
+import org.dromara.x.file.storage.core.UploadPretreatment;
+import org.dromara.x.file.storage.core.exception.FileStorageRuntimeException;
+import org.dromara.x.file.storage.core.file.FileWrapper;
import java.io.File;
import java.io.IOException;
@@ -43,9 +44,12 @@ public boolean save(FileInfo fileInfo,UploadPretreatment pre) {
File newFile = FileUtil.touch(basePath + path,fileInfo.getFilename());
fileInfo.setBasePath(basePath);
fileInfo.setUrl(domain + path + fileInfo.getFilename());
- if (fileInfo.getFileAcl() != null) {
+ if (fileInfo.getFileAcl() != null && pre.getNotSupportAclThrowException()) {
throw new FileStorageRuntimeException("文件上传失败,LocalFile 不支持设置 ACL!platform:" + platform + ",filename:" + fileInfo.getOriginalFilename());
}
+ if (CollUtil.isNotEmpty(fileInfo.getUserMetadata()) && pre.getNotSupportMetadataThrowException()) {
+ throw new FileStorageRuntimeException("文件上传失败,LocalFile 不支持设置 UserMetadata!platform:" + platform + ",filename:" + fileInfo.getOriginalFilename());
+ }
ProgressListener listener = pre.getProgressListener();
try {
diff --git a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/LocalPlusFileStorage.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/LocalPlusFileStorage.java
similarity index 83%
rename from file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/LocalPlusFileStorage.java
rename to x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/LocalPlusFileStorage.java
index 5d36ec2f..a8e5e5dd 100644
--- a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/LocalPlusFileStorage.java
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/LocalPlusFileStorage.java
@@ -1,17 +1,18 @@
-package cn.xuyanwu.spring.file.storage.platform;
+package org.dromara.x.file.storage.core.platform;
+import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
-import cn.xuyanwu.spring.file.storage.FileInfo;
-import cn.xuyanwu.spring.file.storage.FileStorageProperties.LocalPlusConfig;
-import cn.xuyanwu.spring.file.storage.ProgressInputStream;
-import cn.xuyanwu.spring.file.storage.ProgressListener;
-import cn.xuyanwu.spring.file.storage.UploadPretreatment;
-import cn.xuyanwu.spring.file.storage.exception.FileStorageRuntimeException;
-import cn.xuyanwu.spring.file.storage.file.FileWrapper;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
+import org.dromara.x.file.storage.core.FileInfo;
+import org.dromara.x.file.storage.core.FileStorageProperties.LocalPlusConfig;
+import org.dromara.x.file.storage.core.ProgressInputStream;
+import org.dromara.x.file.storage.core.ProgressListener;
+import org.dromara.x.file.storage.core.UploadPretreatment;
+import org.dromara.x.file.storage.core.exception.FileStorageRuntimeException;
+import org.dromara.x.file.storage.core.file.FileWrapper;
import java.io.File;
import java.io.IOException;
@@ -59,9 +60,12 @@ public boolean save(FileInfo fileInfo,UploadPretreatment pre) {
fileInfo.setBasePath(basePath);
String newFileKey = getFileKey(fileInfo);
fileInfo.setUrl(domain + newFileKey);
- if (fileInfo.getFileAcl() != null) {
+ if (fileInfo.getFileAcl() != null && pre.getNotSupportAclThrowException()) {
throw new FileStorageRuntimeException("文件上传失败,LocalFile 不支持设置 ACL!platform:" + platform + ",filename:" + fileInfo.getOriginalFilename());
}
+ if (CollUtil.isNotEmpty(fileInfo.getUserMetadata()) && pre.getNotSupportMetadataThrowException()) {
+ throw new FileStorageRuntimeException("文件上传失败,LocalFile 不支持设置 Metadata!platform:" + platform + ",filename:" + fileInfo.getOriginalFilename());
+ }
ProgressListener listener = pre.getProgressListener();
try {
diff --git a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/MinioFileStorage.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/MinioFileStorage.java
similarity index 90%
rename from file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/MinioFileStorage.java
rename to x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/MinioFileStorage.java
index 6406c46d..c4dd745d 100644
--- a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/MinioFileStorage.java
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/MinioFileStorage.java
@@ -1,18 +1,18 @@
-package cn.xuyanwu.spring.file.storage.platform;
+package org.dromara.x.file.storage.core.platform;
import cn.hutool.core.util.StrUtil;
-import cn.xuyanwu.spring.file.storage.FileInfo;
-import cn.xuyanwu.spring.file.storage.FileStorageProperties.MinioConfig;
-import cn.xuyanwu.spring.file.storage.ProgressInputStream;
-import cn.xuyanwu.spring.file.storage.ProgressListener;
-import cn.xuyanwu.spring.file.storage.UploadPretreatment;
-import cn.xuyanwu.spring.file.storage.exception.FileStorageRuntimeException;
import io.minio.*;
import io.minio.errors.*;
import io.minio.http.Method;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
+import org.dromara.x.file.storage.core.FileInfo;
+import org.dromara.x.file.storage.core.FileStorageProperties.MinioConfig;
+import org.dromara.x.file.storage.core.ProgressInputStream;
+import org.dromara.x.file.storage.core.ProgressListener;
+import org.dromara.x.file.storage.core.UploadPretreatment;
+import org.dromara.x.file.storage.core.exception.FileStorageRuntimeException;
import java.io.ByteArrayInputStream;
import java.io.IOException;
@@ -67,7 +67,7 @@ public boolean save(FileInfo fileInfo,UploadPretreatment pre) {
fileInfo.setBasePath(basePath);
String newFileKey = getFileKey(fileInfo);
fileInfo.setUrl(domain + newFileKey);
- if (fileInfo.getFileAcl() != null) {
+ if (fileInfo.getFileAcl() != null && pre.getNotSupportAclThrowException()) {
throw new FileStorageRuntimeException("文件上传失败,MinIO 不支持设置 ACL!platform:" + platform + ",filename:" + fileInfo.getOriginalFilename());
}
ProgressListener listener = pre.getProgressListener();
@@ -77,7 +77,10 @@ public boolean save(FileInfo fileInfo,UploadPretreatment pre) {
Long size = fileInfo.getSize();
client.putObject(PutObjectArgs.builder().bucket(bucketName).object(newFileKey)
.stream(listener == null ? in : new ProgressInputStream(in,listener,size),size,-1)
- .contentType(fileInfo.getContentType()).build());
+ .contentType(fileInfo.getContentType())
+ .headers(fileInfo.getMetadata())
+ .userMetadata(fileInfo.getUserMetadata())
+ .build());
byte[] thumbnailBytes = pre.getThumbnailBytes();
if (thumbnailBytes != null) { //上传缩略图
@@ -85,7 +88,10 @@ public boolean save(FileInfo fileInfo,UploadPretreatment pre) {
fileInfo.setThUrl(domain + newThFileKey);
client.putObject(PutObjectArgs.builder().bucket(bucketName).object(newThFileKey)
.stream(new ByteArrayInputStream(thumbnailBytes),thumbnailBytes.length,-1)
- .contentType(fileInfo.getThContentType()).build());
+ .contentType(fileInfo.getThContentType())
+ .headers(fileInfo.getThMetadata())
+ .userMetadata(fileInfo.getThUserMetadata())
+ .build());
}
return true;
@@ -143,6 +149,11 @@ public String generateThPresignedUrl(FileInfo fileInfo,Date expiration) {
}
}
+ @Override
+ public boolean isSupportMetadata() {
+ return true;
+ }
+
@Override
public boolean delete(FileInfo fileInfo) {
MinioClient client = getClient();
diff --git a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/MinioFileStorageClientFactory.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/MinioFileStorageClientFactory.java
similarity index 89%
rename from file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/MinioFileStorageClientFactory.java
rename to x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/MinioFileStorageClientFactory.java
index 567ec45e..4793baf1 100644
--- a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/MinioFileStorageClientFactory.java
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/MinioFileStorageClientFactory.java
@@ -1,10 +1,10 @@
-package cn.xuyanwu.spring.file.storage.platform;
+package org.dromara.x.file.storage.core.platform;
-import cn.xuyanwu.spring.file.storage.FileStorageProperties.MinioConfig;
import io.minio.MinioClient;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
+import org.dromara.x.file.storage.core.FileStorageProperties.MinioConfig;
/**
* MinIO 存储平台的 Client 工厂
diff --git a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/QiniuKodoFileStorage.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/QiniuKodoFileStorage.java
similarity index 75%
rename from file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/QiniuKodoFileStorage.java
rename to x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/QiniuKodoFileStorage.java
index 9b5cc75c..43190553 100644
--- a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/QiniuKodoFileStorage.java
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/QiniuKodoFileStorage.java
@@ -1,19 +1,21 @@
-package cn.xuyanwu.spring.file.storage.platform;
+package org.dromara.x.file.storage.core.platform;
+import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
-import cn.xuyanwu.spring.file.storage.FileInfo;
-import cn.xuyanwu.spring.file.storage.FileStorageProperties.QiniuKodoConfig;
-import cn.xuyanwu.spring.file.storage.ProgressInputStream;
-import cn.xuyanwu.spring.file.storage.ProgressListener;
-import cn.xuyanwu.spring.file.storage.UploadPretreatment;
-import cn.xuyanwu.spring.file.storage.exception.FileStorageRuntimeException;
-import cn.xuyanwu.spring.file.storage.platform.QiniuKodoFileStorageClientFactory.QiniuKodoClient;
import com.qiniu.common.QiniuException;
import com.qiniu.storage.BucketManager;
import com.qiniu.storage.UploadManager;
+import com.qiniu.util.StringMap;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
+import org.dromara.x.file.storage.core.FileInfo;
+import org.dromara.x.file.storage.core.FileStorageProperties.QiniuKodoConfig;
+import org.dromara.x.file.storage.core.ProgressInputStream;
+import org.dromara.x.file.storage.core.ProgressListener;
+import org.dromara.x.file.storage.core.UploadPretreatment;
+import org.dromara.x.file.storage.core.exception.FileStorageRuntimeException;
+import org.dromara.x.file.storage.core.platform.QiniuKodoFileStorageClientFactory.QiniuKodoClient;
import java.io.ByteArrayInputStream;
import java.io.IOException;
@@ -68,7 +70,7 @@ public boolean save(FileInfo fileInfo,UploadPretreatment pre) {
fileInfo.setBasePath(basePath);
String newFileKey = getFileKey(fileInfo);
fileInfo.setUrl(domain + newFileKey);
- if (fileInfo.getFileAcl() != null) {
+ if (fileInfo.getFileAcl() != null && pre.getNotSupportAclThrowException()) {
throw new FileStorageRuntimeException("文件上传失败,七牛云 Kodo 不支持设置 ACL!platform:" + platform + ",filename:" + fileInfo.getOriginalFilename());
}
ProgressListener listener = pre.getProgressListener();
@@ -79,13 +81,13 @@ public boolean save(FileInfo fileInfo,UploadPretreatment pre) {
UploadManager uploadManager = client.getUploadManager();
String token = client.getAuth().uploadToken(bucketName);
uploadManager.put(listener == null ? in : new ProgressInputStream(in,listener,fileInfo.getSize()),
- newFileKey,token,null,fileInfo.getContentType());
+ newFileKey,token,getObjectMetadata(fileInfo),fileInfo.getContentType());
byte[] thumbnailBytes = pre.getThumbnailBytes();
if (thumbnailBytes != null) { //上传缩略图
String newThFileKey = getThFileKey(fileInfo);
fileInfo.setThUrl(domain + newThFileKey);
- uploadManager.put(new ByteArrayInputStream(thumbnailBytes),newThFileKey,token,null,fileInfo.getThContentType());
+ uploadManager.put(new ByteArrayInputStream(thumbnailBytes),newThFileKey,token,getThObjectMetadata(fileInfo),fileInfo.getThContentType());
}
return true;
@@ -98,6 +100,34 @@ public boolean save(FileInfo fileInfo,UploadPretreatment pre) {
}
}
+ /**
+ * 获取对象的元数据
+ */
+ public StringMap getObjectMetadata(FileInfo fileInfo) {
+ StringMap params = new StringMap();
+ if (CollUtil.isNotEmpty(fileInfo.getMetadata())) {
+ fileInfo.getMetadata().forEach(params::put);
+ }
+ if (CollUtil.isNotEmpty(fileInfo.getUserMetadata())) {
+ fileInfo.getUserMetadata().forEach((key,value) -> params.put(key.startsWith("x-qn-meta-") ? key : ("x-qn-meta-" + key),value));
+ }
+ return params;
+ }
+
+ /**
+ * 获取缩略图对象的元数据
+ */
+ public StringMap getThObjectMetadata(FileInfo fileInfo) {
+ StringMap params = new StringMap();
+ if (CollUtil.isNotEmpty(fileInfo.getThMetadata())) {
+ fileInfo.getThMetadata().forEach(params::put);
+ }
+ if (CollUtil.isNotEmpty(fileInfo.getThUserMetadata())) {
+ fileInfo.getThUserMetadata().forEach((key,value) -> params.put(key.startsWith("x-qn-meta-") ? key : ("x-qn-meta-" + key),value));
+ }
+ return params;
+ }
+
@Override
public boolean isSupportPresignedUrl() {
return true;
@@ -116,6 +146,11 @@ public String generateThPresignedUrl(FileInfo fileInfo,Date expiration) {
return getClient().getAuth().privateDownloadUrlWithDeadline(fileInfo.getThUrl(),deadline);
}
+ @Override
+ public boolean isSupportMetadata() {
+ return true;
+ }
+
@Override
public boolean delete(FileInfo fileInfo) {
BucketManager manager = getClient().getBucketManager();
diff --git a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/QiniuKodoFileStorageClientFactory.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/QiniuKodoFileStorageClientFactory.java
similarity index 93%
rename from file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/QiniuKodoFileStorageClientFactory.java
rename to x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/QiniuKodoFileStorageClientFactory.java
index 5c071f2f..bd21228e 100644
--- a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/QiniuKodoFileStorageClientFactory.java
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/QiniuKodoFileStorageClientFactory.java
@@ -1,7 +1,5 @@
-package cn.xuyanwu.spring.file.storage.platform;
+package org.dromara.x.file.storage.core.platform;
-import cn.xuyanwu.spring.file.storage.FileStorageProperties.QiniuKodoConfig;
-import cn.xuyanwu.spring.file.storage.platform.QiniuKodoFileStorageClientFactory.QiniuKodoClient;
import com.qiniu.storage.BucketManager;
import com.qiniu.storage.Configuration;
import com.qiniu.storage.Region;
@@ -10,6 +8,8 @@
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
+import org.dromara.x.file.storage.core.FileStorageProperties.QiniuKodoConfig;
+import org.dromara.x.file.storage.core.platform.QiniuKodoFileStorageClientFactory.QiniuKodoClient;
/**
* 七牛云 Kodo 存储平台的 Client 工厂
diff --git a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/SftpFileStorage.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/SftpFileStorage.java
similarity index 87%
rename from file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/SftpFileStorage.java
rename to x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/SftpFileStorage.java
index 8c7a03f6..a2afa51f 100644
--- a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/SftpFileStorage.java
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/SftpFileStorage.java
@@ -1,18 +1,19 @@
-package cn.xuyanwu.spring.file.storage.platform;
+package org.dromara.x.file.storage.core.platform;
+import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.ssh.JschRuntimeException;
import cn.hutool.extra.ssh.Sftp;
-import cn.xuyanwu.spring.file.storage.FileInfo;
-import cn.xuyanwu.spring.file.storage.FileStorageProperties.SftpConfig;
-import cn.xuyanwu.spring.file.storage.ProgressInputStream;
-import cn.xuyanwu.spring.file.storage.ProgressListener;
-import cn.xuyanwu.spring.file.storage.UploadPretreatment;
-import cn.xuyanwu.spring.file.storage.exception.FileStorageRuntimeException;
import com.jcraft.jsch.SftpException;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
+import org.dromara.x.file.storage.core.FileInfo;
+import org.dromara.x.file.storage.core.FileStorageProperties.SftpConfig;
+import org.dromara.x.file.storage.core.ProgressInputStream;
+import org.dromara.x.file.storage.core.ProgressListener;
+import org.dromara.x.file.storage.core.UploadPretreatment;
+import org.dromara.x.file.storage.core.exception.FileStorageRuntimeException;
import java.io.ByteArrayInputStream;
import java.io.IOException;
@@ -82,9 +83,12 @@ public boolean save(FileInfo fileInfo,UploadPretreatment pre) {
fileInfo.setBasePath(basePath);
String newFileKey = getFileKey(fileInfo);
fileInfo.setUrl(domain + newFileKey);
- if (fileInfo.getFileAcl() != null) {
+ if (fileInfo.getFileAcl() != null && pre.getNotSupportAclThrowException()) {
throw new FileStorageRuntimeException("文件上传失败,SFTP 不支持设置 ACL!platform:" + platform + ",filename:" + fileInfo.getOriginalFilename());
}
+ if (CollUtil.isNotEmpty(fileInfo.getUserMetadata()) && pre.getNotSupportMetadataThrowException()) {
+ throw new FileStorageRuntimeException("文件上传失败,SFTP 不支持设置 UserMetadata!platform:" + platform + ",filename:" + fileInfo.getOriginalFilename());
+ }
ProgressListener listener = pre.getProgressListener();
Sftp client = getClient();
diff --git a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/SftpFileStorageClientFactory.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/SftpFileStorageClientFactory.java
similarity index 96%
rename from file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/SftpFileStorageClientFactory.java
rename to x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/SftpFileStorageClientFactory.java
index f51a63e4..4aa217cd 100644
--- a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/SftpFileStorageClientFactory.java
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/SftpFileStorageClientFactory.java
@@ -1,4 +1,4 @@
-package cn.xuyanwu.spring.file.storage.platform;
+package org.dromara.x.file.storage.core.platform;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.StrUtil;
@@ -6,8 +6,6 @@
import cn.hutool.extra.ftp.FtpException;
import cn.hutool.extra.ssh.JschUtil;
import cn.hutool.extra.ssh.Sftp;
-import cn.xuyanwu.spring.file.storage.FileStorageProperties.SftpConfig;
-import cn.xuyanwu.spring.file.storage.exception.FileStorageRuntimeException;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import lombok.AllArgsConstructor;
@@ -20,6 +18,8 @@
import org.apache.commons.pool2.impl.DefaultPooledObject;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
+import org.dromara.x.file.storage.core.FileStorageProperties.SftpConfig;
+import org.dromara.x.file.storage.core.exception.FileStorageRuntimeException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
diff --git a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/TencentCosFileStorage.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/TencentCosFileStorage.java
similarity index 85%
rename from file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/TencentCosFileStorage.java
rename to x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/TencentCosFileStorage.java
index dc275da9..29c5b5ce 100644
--- a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/TencentCosFileStorage.java
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/TencentCosFileStorage.java
@@ -1,18 +1,19 @@
-package cn.xuyanwu.spring.file.storage.platform;
+package org.dromara.x.file.storage.core.platform;
+import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.StrUtil;
-import cn.xuyanwu.spring.file.storage.FileInfo;
-import cn.xuyanwu.spring.file.storage.FileStorageProperties.TencentCosConfig;
-import cn.xuyanwu.spring.file.storage.ProgressListener;
-import cn.xuyanwu.spring.file.storage.UploadPretreatment;
-import cn.xuyanwu.spring.file.storage.exception.FileStorageRuntimeException;
import com.qcloud.cos.COSClient;
import com.qcloud.cos.event.ProgressEventType;
import com.qcloud.cos.model.*;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
+import org.dromara.x.file.storage.core.FileInfo;
+import org.dromara.x.file.storage.core.FileStorageProperties.TencentCosConfig;
+import org.dromara.x.file.storage.core.ProgressListener;
+import org.dromara.x.file.storage.core.UploadPretreatment;
+import org.dromara.x.file.storage.core.exception.FileStorageRuntimeException;
import java.io.ByteArrayInputStream;
import java.io.IOException;
@@ -76,14 +77,12 @@ public boolean save(FileInfo fileInfo,UploadPretreatment pre) {
String newFileKey = getFileKey(fileInfo);
fileInfo.setUrl(domain + newFileKey);
CannedAccessControlList fileAcl = getAcl(fileInfo.getFileAcl());
+ ObjectMetadata metadata = getObjectMetadata(fileInfo);
ProgressListener listener = pre.getProgressListener();
COSClient client = getClient();
boolean useMultipartUpload = fileInfo.getSize() >= multipartThreshold;
String uploadId = null;
try (InputStream in = pre.getFileWrapper().getInputStream()) {
- ObjectMetadata metadata = new ObjectMetadata();
- metadata.setContentLength(fileInfo.getSize());
- metadata.setContentType(fileInfo.getContentType());
if (useMultipartUpload) {//分片上传
InitiateMultipartUploadRequest initiateMultipartUploadRequest = new InitiateMultipartUploadRequest(bucketName,newFileKey,metadata);
initiateMultipartUploadRequest.setCannedACL(fileAcl);
@@ -135,9 +134,7 @@ public boolean save(FileInfo fileInfo,UploadPretreatment pre) {
if (thumbnailBytes != null) { //上传缩略图
String newThFileKey = getThFileKey(fileInfo);
fileInfo.setThUrl(domain + newThFileKey);
- ObjectMetadata thMetadata = new ObjectMetadata();
- thMetadata.setContentLength(thumbnailBytes.length);
- thMetadata.setContentType(fileInfo.getThContentType());
+ ObjectMetadata thMetadata = getThObjectMetadata(fileInfo);
PutObjectRequest request = new PutObjectRequest(bucketName,newThFileKey,new ByteArrayInputStream(thumbnailBytes),thMetadata);
request.setCannedAcl(getAcl(fileInfo.getThFileAcl()));
client.putObject(request);
@@ -174,6 +171,34 @@ public CannedAccessControlList getAcl(Object acl) {
}
}
+ /**
+ * 获取对象的元数据
+ */
+ public ObjectMetadata getObjectMetadata(FileInfo fileInfo) {
+ ObjectMetadata metadata = new ObjectMetadata();
+ metadata.setContentLength(fileInfo.getSize());
+ metadata.setContentType(fileInfo.getContentType());
+ metadata.setUserMetadata(fileInfo.getUserMetadata());
+ if (CollUtil.isNotEmpty(fileInfo.getMetadata())) {
+ fileInfo.getMetadata().forEach(metadata::setHeader);
+ }
+ return metadata;
+ }
+
+ /**
+ * 获取缩略图对象的元数据
+ */
+ public ObjectMetadata getThObjectMetadata(FileInfo fileInfo) {
+ ObjectMetadata metadata = new ObjectMetadata();
+ metadata.setContentLength(fileInfo.getThSize());
+ metadata.setContentType(fileInfo.getThContentType());
+ metadata.setUserMetadata(fileInfo.getThUserMetadata());
+ if (CollUtil.isNotEmpty(fileInfo.getThMetadata())) {
+ fileInfo.getThMetadata().forEach(metadata::setHeader);
+ }
+ return metadata;
+ }
+
@Override
public boolean isSupportPresignedUrl() {
return true;
@@ -214,6 +239,11 @@ public boolean setThFileAcl(FileInfo fileInfo,Object acl) {
return true;
}
+ @Override
+ public boolean isSupportMetadata() {
+ return true;
+ }
+
@Override
public boolean delete(FileInfo fileInfo) {
COSClient client = getClient();
diff --git a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/TencentCosFileStorageClientFactory.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/TencentCosFileStorageClientFactory.java
similarity index 92%
rename from file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/TencentCosFileStorageClientFactory.java
rename to x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/TencentCosFileStorageClientFactory.java
index 91376e94..7e39f67e 100644
--- a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/TencentCosFileStorageClientFactory.java
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/TencentCosFileStorageClientFactory.java
@@ -1,7 +1,6 @@
-package cn.xuyanwu.spring.file.storage.platform;
+package org.dromara.x.file.storage.core.platform;
import cn.hutool.core.util.StrUtil;
-import cn.xuyanwu.spring.file.storage.FileStorageProperties.TencentCosConfig;
import com.qcloud.cos.COSClient;
import com.qcloud.cos.ClientConfig;
import com.qcloud.cos.auth.BasicCOSCredentials;
@@ -9,6 +8,7 @@
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
+import org.dromara.x.file.storage.core.FileStorageProperties.TencentCosConfig;
/**
* 腾讯云 COS 存储平台的 Client 工厂
diff --git a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/UpyunUssFileStorage.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/UpyunUssFileStorage.java
similarity index 73%
rename from file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/UpyunUssFileStorage.java
rename to x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/UpyunUssFileStorage.java
index e6028d89..802d27a5 100644
--- a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/UpyunUssFileStorage.java
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/UpyunUssFileStorage.java
@@ -1,13 +1,8 @@
-package cn.xuyanwu.spring.file.storage.platform;
+package org.dromara.x.file.storage.core.platform;
+import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.StrUtil;
-import cn.xuyanwu.spring.file.storage.FileInfo;
-import cn.xuyanwu.spring.file.storage.FileStorageProperties.UpyunUssConfig;
-import cn.xuyanwu.spring.file.storage.ProgressInputStream;
-import cn.xuyanwu.spring.file.storage.ProgressListener;
-import cn.xuyanwu.spring.file.storage.UploadPretreatment;
-import cn.xuyanwu.spring.file.storage.exception.FileStorageRuntimeException;
import com.upyun.RestManager;
import com.upyun.UpException;
import lombok.Getter;
@@ -15,6 +10,12 @@
import lombok.Setter;
import okhttp3.Response;
import okhttp3.ResponseBody;
+import org.dromara.x.file.storage.core.FileInfo;
+import org.dromara.x.file.storage.core.FileStorageProperties.UpyunUssConfig;
+import org.dromara.x.file.storage.core.ProgressInputStream;
+import org.dromara.x.file.storage.core.ProgressListener;
+import org.dromara.x.file.storage.core.UploadPretreatment;
+import org.dromara.x.file.storage.core.exception.FileStorageRuntimeException;
import java.io.ByteArrayInputStream;
import java.io.IOException;
@@ -68,7 +69,7 @@ public boolean save(FileInfo fileInfo,UploadPretreatment pre) {
fileInfo.setBasePath(basePath);
String newFileKey = getFileKey(fileInfo);
fileInfo.setUrl(domain + newFileKey);
- if (fileInfo.getFileAcl() != null) {
+ if (fileInfo.getFileAcl() != null && pre.getNotSupportAclThrowException()) {
throw new FileStorageRuntimeException("文件上传失败,又拍云 USS 不支持设置 ACL!platform:" + platform + ",filename:" + fileInfo.getOriginalFilename());
}
ProgressListener listener = pre.getProgressListener();
@@ -76,12 +77,9 @@ public boolean save(FileInfo fileInfo,UploadPretreatment pre) {
RestManager manager = getClient();
try (InputStream in = pre.getFileWrapper().getInputStream()) {
//又拍云 USS 的 SDK 使用的是 REST API ,看文档不是区分大小文件的,测试大文件也是流式传输的,边读边传,不会占用大量内存
- HashMap params = new HashMap<>();
- params.put(RestManager.PARAMS.CONTENT_TYPE.getValue(),fileInfo.getContentType());
- params.put("Content-Length",String.valueOf(fileInfo.getSize()));
try (Response result = manager.writeFile(newFileKey,
listener == null ? in : new ProgressInputStream(in,listener,fileInfo.getSize()),
- params)) {
+ getObjectMetadata(fileInfo))) {
if (!result.isSuccessful()) {
throw new UpException(result.toString());
}
@@ -91,9 +89,7 @@ public boolean save(FileInfo fileInfo,UploadPretreatment pre) {
if (thumbnailBytes != null) { //上传缩略图
String newThFileKey = getThFileKey(fileInfo);
fileInfo.setThUrl(domain + newThFileKey);
- HashMap thParams = new HashMap<>();
- thParams.put(RestManager.PARAMS.CONTENT_TYPE.getValue(),fileInfo.getThContentType());
- Response thResult = manager.writeFile(newThFileKey,new ByteArrayInputStream(thumbnailBytes),thParams);
+ Response thResult = manager.writeFile(newThFileKey,new ByteArrayInputStream(thumbnailBytes),getThObjectMetadata(fileInfo));
if (!thResult.isSuccessful()) {
throw new UpException(thResult.toString());
}
@@ -109,6 +105,44 @@ public boolean save(FileInfo fileInfo,UploadPretreatment pre) {
}
}
+
+ /**
+ * 获取对象的元数据
+ */
+ public HashMap getObjectMetadata(FileInfo fileInfo) {
+ HashMap params = new HashMap<>();
+ params.put(RestManager.PARAMS.CONTENT_TYPE.getValue(),fileInfo.getContentType());
+ params.put("Content-Length",String.valueOf(fileInfo.getSize()));
+ if (CollUtil.isNotEmpty(fileInfo.getMetadata())) {
+ params.putAll(fileInfo.getMetadata());
+ }
+ if (CollUtil.isNotEmpty(fileInfo.getUserMetadata())) {
+ fileInfo.getUserMetadata().forEach((key,value) -> params.put(key.startsWith("x-upyun-meta-") ? key : ("x-upyun-meta-" + key),value));
+ }
+ return params;
+ }
+
+ /**
+ * 获取缩略图对象的元数据
+ */
+ public HashMap getThObjectMetadata(FileInfo fileInfo) {
+ HashMap params = new HashMap<>();
+ params.put(RestManager.PARAMS.CONTENT_TYPE.getValue(),fileInfo.getThContentType());
+ params.put("Content-Length",String.valueOf(fileInfo.getThSize()));
+ if (CollUtil.isNotEmpty(fileInfo.getThMetadata())) {
+ params.putAll(fileInfo.getThMetadata());
+ }
+ if (CollUtil.isNotEmpty(fileInfo.getThUserMetadata())) {
+ fileInfo.getThUserMetadata().forEach((key,value) -> params.put(key.startsWith("x-upyun-meta-") ? key : ("x-upyun-meta-" + key),value));
+ }
+ return params;
+ }
+
+ @Override
+ public boolean isSupportMetadata() {
+ return true;
+ }
+
@Override
public boolean delete(FileInfo fileInfo) {
RestManager manager = getClient();
diff --git a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/UpyunUssFileStorageClientFactory.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/UpyunUssFileStorageClientFactory.java
similarity index 89%
rename from file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/UpyunUssFileStorageClientFactory.java
rename to x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/UpyunUssFileStorageClientFactory.java
index 509fd68a..b91ba9b4 100644
--- a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/UpyunUssFileStorageClientFactory.java
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/UpyunUssFileStorageClientFactory.java
@@ -1,10 +1,10 @@
-package cn.xuyanwu.spring.file.storage.platform;
+package org.dromara.x.file.storage.core.platform;
-import cn.xuyanwu.spring.file.storage.FileStorageProperties.UpyunUssConfig;
import com.upyun.RestManager;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
+import org.dromara.x.file.storage.core.FileStorageProperties.UpyunUssConfig;
/**
* 又拍云 USS 存储平台的 Client 工厂
diff --git a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/WebDavFileStorage.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/WebDavFileStorage.java
similarity index 86%
rename from file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/WebDavFileStorage.java
rename to x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/WebDavFileStorage.java
index afaf5043..9931253b 100644
--- a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/WebDavFileStorage.java
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/WebDavFileStorage.java
@@ -1,19 +1,20 @@
-package cn.xuyanwu.spring.file.storage.platform;
+package org.dromara.x.file.storage.core.platform;
+import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.util.StrUtil;
-import cn.xuyanwu.spring.file.storage.FileInfo;
-import cn.xuyanwu.spring.file.storage.FileStorageProperties.WebDavConfig;
-import cn.xuyanwu.spring.file.storage.ProgressInputStream;
-import cn.xuyanwu.spring.file.storage.ProgressListener;
-import cn.xuyanwu.spring.file.storage.UploadPretreatment;
-import cn.xuyanwu.spring.file.storage.exception.FileStorageRuntimeException;
-import cn.xuyanwu.spring.file.storage.util.Tools;
import com.github.sardine.Sardine;
import com.github.sardine.impl.SardineException;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
+import org.dromara.x.file.storage.core.FileInfo;
+import org.dromara.x.file.storage.core.FileStorageProperties.WebDavConfig;
+import org.dromara.x.file.storage.core.ProgressInputStream;
+import org.dromara.x.file.storage.core.ProgressListener;
+import org.dromara.x.file.storage.core.UploadPretreatment;
+import org.dromara.x.file.storage.core.exception.FileStorageRuntimeException;
+import org.dromara.x.file.storage.core.util.Tools;
import java.io.IOException;
import java.io.InputStream;
@@ -92,9 +93,12 @@ public boolean save(FileInfo fileInfo,UploadPretreatment pre) {
fileInfo.setBasePath(basePath);
String newFileKey = getFileKey(fileInfo);
fileInfo.setUrl(domain + newFileKey);
- if (fileInfo.getFileAcl() != null) {
+ if (fileInfo.getFileAcl() != null && pre.getNotSupportAclThrowException()) {
throw new FileStorageRuntimeException("文件上传失败,WebDAV 不支持设置 ACL!platform:" + platform + ",filename:" + fileInfo.getOriginalFilename());
}
+ if (CollUtil.isNotEmpty(fileInfo.getUserMetadata()) && pre.getNotSupportMetadataThrowException()) {
+ throw new FileStorageRuntimeException("文件上传失败,WebDAV 不支持设置 UserMetadata!platform:" + platform + ",filename:" + fileInfo.getOriginalFilename());
+ }
ProgressListener listener = pre.getProgressListener();
Sardine client = getClient();
diff --git a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/WebDavFileStorageClientFactory.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/WebDavFileStorageClientFactory.java
similarity index 87%
rename from file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/WebDavFileStorageClientFactory.java
rename to x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/WebDavFileStorageClientFactory.java
index 80db3482..f97bae63 100644
--- a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/platform/WebDavFileStorageClientFactory.java
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/platform/WebDavFileStorageClientFactory.java
@@ -1,13 +1,13 @@
-package cn.xuyanwu.spring.file.storage.platform;
+package org.dromara.x.file.storage.core.platform;
import cn.hutool.core.util.URLUtil;
-import cn.xuyanwu.spring.file.storage.FileStorageProperties.WebDavConfig;
-import cn.xuyanwu.spring.file.storage.exception.FileStorageRuntimeException;
import com.github.sardine.Sardine;
import com.github.sardine.SardineFactory;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
+import org.dromara.x.file.storage.core.FileStorageProperties.WebDavConfig;
+import org.dromara.x.file.storage.core.exception.FileStorageRuntimeException;
import java.io.IOException;
diff --git a/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/recorder/DefaultFileRecorder.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/recorder/DefaultFileRecorder.java
new file mode 100644
index 00000000..d69b7623
--- /dev/null
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/recorder/DefaultFileRecorder.java
@@ -0,0 +1,24 @@
+package org.dromara.x.file.storage.core.recorder;
+
+import org.dromara.x.file.storage.core.FileInfo;
+import org.dromara.x.file.storage.core.exception.FileStorageRuntimeException;
+
+/**
+ * 默认的文件记录者类,此类并不能真正保存、查询、删除记录,只是用来脱离数据库运行,保证文件上传功能可以正常使用
+ */
+public class DefaultFileRecorder implements FileRecorder {
+ @Override
+ public boolean save(FileInfo fileInfo) {
+ return true;
+ }
+
+ @Override
+ public FileInfo getByUrl(String url) {
+ throw new FileStorageRuntimeException("尚未实现 FileRecorder 接口,暂时无法使用此功能,参考文档:https://x-file-storage.xuyanwu.cn/#/%E5%9F%BA%E7%A1%80%E5%8A%9F%E8%83%BD?id=%E4%BF%9D%E5%AD%98%E4%B8%8A%E4%BC%A0%E8%AE%B0%E5%BD%95");
+ }
+
+ @Override
+ public boolean delete(String url) {
+ return true;
+ }
+}
diff --git a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/recorder/FileRecorder.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/recorder/FileRecorder.java
similarity index 76%
rename from file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/recorder/FileRecorder.java
rename to x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/recorder/FileRecorder.java
index 8bbea739..96af09e1 100644
--- a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/recorder/FileRecorder.java
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/recorder/FileRecorder.java
@@ -1,6 +1,6 @@
-package cn.xuyanwu.spring.file.storage.recorder;
+package org.dromara.x.file.storage.core.recorder;
-import cn.xuyanwu.spring.file.storage.FileInfo;
+import org.dromara.x.file.storage.core.FileInfo;
/**
* 文件记录记录者接口
diff --git a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/tika/ContentTypeDetect.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/tika/ContentTypeDetect.java
similarity index 88%
rename from file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/tika/ContentTypeDetect.java
rename to x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/tika/ContentTypeDetect.java
index d78fa546..4d2bfbd5 100644
--- a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/tika/ContentTypeDetect.java
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/tika/ContentTypeDetect.java
@@ -1,4 +1,4 @@
-package cn.xuyanwu.spring.file.storage.tika;
+package org.dromara.x.file.storage.core.tika;
import java.io.File;
import java.io.IOException;
diff --git a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/tika/DefaultTikaFactory.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/tika/DefaultTikaFactory.java
similarity index 89%
rename from file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/tika/DefaultTikaFactory.java
rename to x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/tika/DefaultTikaFactory.java
index 78a5ede6..65713b66 100644
--- a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/tika/DefaultTikaFactory.java
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/tika/DefaultTikaFactory.java
@@ -1,4 +1,4 @@
-package cn.xuyanwu.spring.file.storage.tika;
+package org.dromara.x.file.storage.core.tika;
import org.apache.tika.Tika;
diff --git a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/tika/TikaContentTypeDetect.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/tika/TikaContentTypeDetect.java
similarity index 95%
rename from file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/tika/TikaContentTypeDetect.java
rename to x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/tika/TikaContentTypeDetect.java
index 982229fc..4acdf2ae 100644
--- a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/tika/TikaContentTypeDetect.java
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/tika/TikaContentTypeDetect.java
@@ -1,4 +1,4 @@
-package cn.xuyanwu.spring.file.storage.tika;
+package org.dromara.x.file.storage.core.tika;
import lombok.AllArgsConstructor;
import lombok.Getter;
diff --git a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/tika/TikaFactory.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/tika/TikaFactory.java
similarity index 71%
rename from file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/tika/TikaFactory.java
rename to x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/tika/TikaFactory.java
index cedd6b5c..1149995f 100644
--- a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/tika/TikaFactory.java
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/tika/TikaFactory.java
@@ -1,4 +1,4 @@
-package cn.xuyanwu.spring.file.storage.tika;
+package org.dromara.x.file.storage.core.tika;
import org.apache.tika.Tika;
diff --git a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/util/Tools.java b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/util/Tools.java
similarity index 96%
rename from file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/util/Tools.java
rename to x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/util/Tools.java
index cb4cb69a..055e8dd3 100644
--- a/file-storage-core/src/main/java/cn/xuyanwu/spring/file/storage/util/Tools.java
+++ b/x-file-storage-core/src/main/java/org/dromara/x/file/storage/core/util/Tools.java
@@ -1,4 +1,4 @@
-package cn.xuyanwu.spring.file.storage.util;
+package org.dromara.x.file.storage.core.util;
import java.io.IOException;
import java.io.InputStream;
diff --git a/spring-file-storage/pom.xml b/x-file-storage-spring/pom.xml
similarity index 93%
rename from spring-file-storage/pom.xml
rename to x-file-storage-spring/pom.xml
index 86d37b93..2aa946e2 100644
--- a/spring-file-storage/pom.xml
+++ b/x-file-storage-spring/pom.xml
@@ -3,18 +3,18 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- spring-file-storage-parent
- cn.xuyanwu
- 1.0.3
+ x-file-storage-parent
+ org.dromara.x-file-storage
+ 2.0.0
4.0.0
- spring-file-storage
+ x-file-storage-spring
- cn.xuyanwu
- file-storage-core
+ org.dromara.x-file-storage
+ x-file-storage-core
diff --git a/spring-file-storage/src/main/java/cn/xuyanwu/spring/file/storage/spring/EnableFileStorage.java b/x-file-storage-spring/src/main/java/org/dromara/x/file/storage/spring/EnableFileStorage.java
similarity index 88%
rename from spring-file-storage/src/main/java/cn/xuyanwu/spring/file/storage/spring/EnableFileStorage.java
rename to x-file-storage-spring/src/main/java/org/dromara/x/file/storage/spring/EnableFileStorage.java
index dc6eea13..5bef7626 100644
--- a/spring-file-storage/src/main/java/cn/xuyanwu/spring/file/storage/spring/EnableFileStorage.java
+++ b/x-file-storage-spring/src/main/java/org/dromara/x/file/storage/spring/EnableFileStorage.java
@@ -1,4 +1,4 @@
-package cn.xuyanwu.spring.file.storage.spring;
+package org.dromara.x.file.storage.spring;
import org.springframework.context.annotation.Import;
diff --git a/spring-file-storage/src/main/java/cn/xuyanwu/spring/file/storage/spring/FileStorageAutoConfiguration.java b/x-file-storage-spring/src/main/java/org/dromara/x/file/storage/spring/FileStorageAutoConfiguration.java
similarity index 79%
rename from spring-file-storage/src/main/java/cn/xuyanwu/spring/file/storage/spring/FileStorageAutoConfiguration.java
rename to x-file-storage-spring/src/main/java/org/dromara/x/file/storage/spring/FileStorageAutoConfiguration.java
index 7ff4393c..245976da 100644
--- a/spring-file-storage/src/main/java/cn/xuyanwu/spring/file/storage/spring/FileStorageAutoConfiguration.java
+++ b/x-file-storage-spring/src/main/java/org/dromara/x/file/storage/spring/FileStorageAutoConfiguration.java
@@ -1,19 +1,21 @@
-package cn.xuyanwu.spring.file.storage.spring;
+package org.dromara.x.file.storage.spring;
-import cn.xuyanwu.spring.file.storage.FileStorageService;
-import cn.xuyanwu.spring.file.storage.FileStorageServiceBuilder;
-import cn.xuyanwu.spring.file.storage.aspect.FileStorageAspect;
-import cn.xuyanwu.spring.file.storage.file.FileWrapperAdapter;
-import cn.xuyanwu.spring.file.storage.platform.FileStorage;
-import cn.xuyanwu.spring.file.storage.platform.FileStorageClientFactory;
-import cn.xuyanwu.spring.file.storage.recorder.DefaultFileRecorder;
-import cn.xuyanwu.spring.file.storage.recorder.FileRecorder;
-import cn.xuyanwu.spring.file.storage.spring.file.MultipartFileWrapperAdapter;
-import cn.xuyanwu.spring.file.storage.tika.ContentTypeDetect;
-import cn.xuyanwu.spring.file.storage.tika.DefaultTikaFactory;
-import cn.xuyanwu.spring.file.storage.tika.TikaContentTypeDetect;
-import cn.xuyanwu.spring.file.storage.tika.TikaFactory;
import lombok.extern.slf4j.Slf4j;
+import org.dromara.x.file.storage.core.FileStorageService;
+import org.dromara.x.file.storage.core.FileStorageServiceBuilder;
+import org.dromara.x.file.storage.core.aspect.FileStorageAspect;
+import org.dromara.x.file.storage.core.file.FileWrapperAdapter;
+import org.dromara.x.file.storage.core.platform.FileStorage;
+import org.dromara.x.file.storage.core.platform.FileStorageClientFactory;
+import org.dromara.x.file.storage.core.recorder.DefaultFileRecorder;
+import org.dromara.x.file.storage.core.recorder.FileRecorder;
+import org.dromara.x.file.storage.core.tika.ContentTypeDetect;
+import org.dromara.x.file.storage.core.tika.DefaultTikaFactory;
+import org.dromara.x.file.storage.core.tika.TikaContentTypeDetect;
+import org.dromara.x.file.storage.core.tika.TikaFactory;
+import org.dromara.x.file.storage.spring.SpringFileStorageProperties.SpringLocalConfig;
+import org.dromara.x.file.storage.spring.SpringFileStorageProperties.SpringLocalPlusConfig;
+import org.dromara.x.file.storage.spring.file.MultipartFileWrapperAdapter;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
@@ -27,9 +29,6 @@
import java.util.List;
-import static cn.xuyanwu.spring.file.storage.spring.SpringFileStorageProperties.SpringLocalConfig;
-import static cn.xuyanwu.spring.file.storage.spring.SpringFileStorageProperties.SpringLocalPlusConfig;
-
@Slf4j
@Configuration
@ConditionalOnMissingBean(FileStorageService.class)
@@ -110,6 +109,7 @@ public FileStorageService fileStorageService(FileRecorder fileRecorder,
if (properties.getEnableUriFileWrapper()) builder.addUriFileWrapperAdapter();
if (properties.getEnableInputStreamFileWrapper()) builder.addInputStreamFileWrapperAdapter();
if (properties.getEnableLocalFileWrapper()) builder.addLocalFileWrapperAdapter();
+ if (properties.getEnableHttpServletRequestFileWrapper()) builder.addHttpServletRequestFileWrapperAdapter();
if (properties.getEnableMultipartFileWrapper())
builder.addFileWrapperAdapter(new MultipartFileWrapperAdapter());
return builder.build();
diff --git a/spring-file-storage/src/main/java/cn/xuyanwu/spring/file/storage/spring/SpringFileStorageProperties.java b/x-file-storage-spring/src/main/java/org/dromara/x/file/storage/spring/SpringFileStorageProperties.java
similarity index 91%
rename from spring-file-storage/src/main/java/cn/xuyanwu/spring/file/storage/spring/SpringFileStorageProperties.java
rename to x-file-storage-spring/src/main/java/org/dromara/x/file/storage/spring/SpringFileStorageProperties.java
index d1210cf7..0ba4b642 100644
--- a/spring-file-storage/src/main/java/cn/xuyanwu/spring/file/storage/spring/SpringFileStorageProperties.java
+++ b/x-file-storage-spring/src/main/java/org/dromara/x/file/storage/spring/SpringFileStorageProperties.java
@@ -1,9 +1,9 @@
-package cn.xuyanwu.spring.file.storage.spring;
+package org.dromara.x.file.storage.spring;
-import cn.xuyanwu.spring.file.storage.FileStorageProperties;
-import cn.xuyanwu.spring.file.storage.FileStorageProperties.*;
import lombok.Data;
import lombok.EqualsAndHashCode;
+import org.dromara.x.file.storage.core.FileStorageProperties;
+import org.dromara.x.file.storage.core.FileStorageProperties.*;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@@ -15,7 +15,7 @@
@Data
@Component
@ConditionalOnMissingBean(SpringFileStorageProperties.class)
-@ConfigurationProperties(prefix = "spring.file-storage")
+@ConfigurationProperties(prefix = "dromara.x-file-storage")
public class SpringFileStorageProperties {
/**
@@ -26,6 +26,14 @@ public class SpringFileStorageProperties {
* 缩略图后缀,例如【.min.jpg】【.png】
*/
private String thumbnailSuffix = ".min.jpg";
+ /**
+ * 上传时不支持元数据时抛出异常
+ */
+ private Boolean uploadNotSupportMetadataThrowException = true;
+ /**
+ * 上传时不支持 ACL 时抛出异常
+ */
+ private Boolean uploadNotSupportAclThrowException = true;
/**
* 启用 byte[] 文件包装适配器
*/
@@ -42,6 +50,10 @@ public class SpringFileStorageProperties {
* 启用本地文件包装适配器
*/
private Boolean enableLocalFileWrapper = true;
+ /**
+ * 启用 HttpServletRequest 文件包装适配器
+ */
+ private Boolean enableHttpServletRequestFileWrapper = true;
/**
* 启用 Multipart 文件包装适配器
*/
@@ -116,6 +128,8 @@ public FileStorageProperties toFileStorageProperties() {
FileStorageProperties properties = new FileStorageProperties();
properties.setDefaultPlatform(defaultPlatform);
properties.setThumbnailSuffix(thumbnailSuffix);
+ properties.setUploadNotSupportMetadataThrowException(uploadNotSupportMetadataThrowException);
+ properties.setUploadNotSupportAclThrowException(uploadNotSupportAclThrowException);
properties.setLocal(local.stream().filter(SpringLocalConfig::getEnableStorage).collect(Collectors.toList()));
properties.setLocalPlus(localPlus.stream().filter(SpringLocalPlusConfig::getEnableStorage).collect(Collectors.toList()));
properties.setHuaweiObs(huaweiObs.stream().filter(SpringHuaweiObsConfig::getEnableStorage).collect(Collectors.toList()));
diff --git a/spring-file-storage/src/main/java/cn/xuyanwu/spring/file/storage/spring/file/MultipartFileWrapper.java b/x-file-storage-spring/src/main/java/org/dromara/x/file/storage/spring/file/MultipartFileWrapper.java
similarity index 90%
rename from spring-file-storage/src/main/java/cn/xuyanwu/spring/file/storage/spring/file/MultipartFileWrapper.java
rename to x-file-storage-spring/src/main/java/org/dromara/x/file/storage/spring/file/MultipartFileWrapper.java
index 314cfc8f..7423233b 100644
--- a/spring-file-storage/src/main/java/cn/xuyanwu/spring/file/storage/spring/file/MultipartFileWrapper.java
+++ b/x-file-storage-spring/src/main/java/org/dromara/x/file/storage/spring/file/MultipartFileWrapper.java
@@ -1,11 +1,11 @@
-package cn.xuyanwu.spring.file.storage.spring.file;
+package org.dromara.x.file.storage.spring.file;
import cn.hutool.core.io.FileUtil;
-import cn.xuyanwu.spring.file.storage.exception.FileStorageRuntimeException;
-import cn.xuyanwu.spring.file.storage.file.FileWrapper;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
+import org.dromara.x.file.storage.core.exception.FileStorageRuntimeException;
+import org.dromara.x.file.storage.core.file.FileWrapper;
import org.springframework.web.multipart.MultipartFile;
import java.io.BufferedInputStream;
diff --git a/spring-file-storage/src/main/java/cn/xuyanwu/spring/file/storage/spring/file/MultipartFileWrapperAdapter.java b/x-file-storage-spring/src/main/java/org/dromara/x/file/storage/spring/file/MultipartFileWrapperAdapter.java
similarity index 86%
rename from spring-file-storage/src/main/java/cn/xuyanwu/spring/file/storage/spring/file/MultipartFileWrapperAdapter.java
rename to x-file-storage-spring/src/main/java/org/dromara/x/file/storage/spring/file/MultipartFileWrapperAdapter.java
index 5aaa4477..8c57de8e 100644
--- a/spring-file-storage/src/main/java/cn/xuyanwu/spring/file/storage/spring/file/MultipartFileWrapperAdapter.java
+++ b/x-file-storage-spring/src/main/java/org/dromara/x/file/storage/spring/file/MultipartFileWrapperAdapter.java
@@ -1,9 +1,9 @@
-package cn.xuyanwu.spring.file.storage.spring.file;
+package org.dromara.x.file.storage.spring.file;
-import cn.xuyanwu.spring.file.storage.file.FileWrapper;
-import cn.xuyanwu.spring.file.storage.file.FileWrapperAdapter;
import lombok.Getter;
import lombok.Setter;
+import org.dromara.x.file.storage.core.file.FileWrapper;
+import org.dromara.x.file.storage.core.file.FileWrapperAdapter;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
diff --git a/spring-file-storage-test/.gitignore b/x-file-storage-test/.gitignore
similarity index 100%
rename from spring-file-storage-test/.gitignore
rename to x-file-storage-test/.gitignore
diff --git a/spring-file-storage-test/mvnw b/x-file-storage-test/mvnw
similarity index 100%
rename from spring-file-storage-test/mvnw
rename to x-file-storage-test/mvnw
diff --git a/spring-file-storage-test/mvnw.cmd b/x-file-storage-test/mvnw.cmd
similarity index 100%
rename from spring-file-storage-test/mvnw.cmd
rename to x-file-storage-test/mvnw.cmd
diff --git a/spring-file-storage-test/pom.xml b/x-file-storage-test/pom.xml
similarity index 85%
rename from spring-file-storage-test/pom.xml
rename to x-file-storage-test/pom.xml
index 082e253f..522c2048 100644
--- a/spring-file-storage-test/pom.xml
+++ b/x-file-storage-test/pom.xml
@@ -10,11 +10,11 @@
- cn.xuyanwu
- spring-file-storage-test
- 1.0.3
- spring-file-storage-test
- spring-file-storage 的测试和演示模块
+ org.dromara.x-file-storage
+ x-file-storage-test
+ 2.0.0
+ x-file-storage-test
+ x-file-storage 的测试和演示模块
1.8
@@ -62,15 +62,15 @@
-
+
-
- com.amazonaws
- aws-java-sdk-s3
- 1.12.429
-
+
+
+
+
+
@@ -122,11 +122,11 @@