From c89e0720058d86dcf835d1bc725db236059ba608 Mon Sep 17 00:00:00 2001 From: quericy Date: Sun, 10 Apr 2022 04:11:34 +0800 Subject: [PATCH] feat: support webdav 1, feat:config webDav and milton in configuration; 2, feat:add event handler in WebDavController; 3, feat:check auth by admin in systemConfig; 4, feat:download webDav file by redirect to site DirectLink; --- pom.xml | 17 ++ .../config/ApplicationContextConfigure.java | 36 ++++ .../config/webdav/MiltonConfiguration.java | 60 +++++++ .../config/webdav/WebDavConfiguration.java | 33 ++++ .../webdav/adapter/WebDavUrlAdapterImpl.java | 41 +++++ .../auth/SystemConfigSecurityManager.java | 130 +++++++++++++++ .../resolver/WebDavRedirectViewResolver.java | 62 +++++++ .../controller/home/WebDavController.java | 157 ++++++++++++++++++ .../zfile/model/constant/ZFileConstant.java | 5 + .../model/entity/webdav/WebDavEntity.java | 112 +++++++++++++ .../zfile/model/entity/webdav/WebDavFile.java | 37 +++++ .../model/entity/webdav/WebDavFolder.java | 41 +++++ .../zhaojun/zfile/util/RegexMatchUtils.java | 61 +++++++ 13 files changed, 792 insertions(+) create mode 100644 src/main/java/im/zhaojun/zfile/config/ApplicationContextConfigure.java create mode 100644 src/main/java/im/zhaojun/zfile/config/webdav/MiltonConfiguration.java create mode 100644 src/main/java/im/zhaojun/zfile/config/webdav/WebDavConfiguration.java create mode 100644 src/main/java/im/zhaojun/zfile/config/webdav/adapter/WebDavUrlAdapterImpl.java create mode 100644 src/main/java/im/zhaojun/zfile/config/webdav/auth/SystemConfigSecurityManager.java create mode 100644 src/main/java/im/zhaojun/zfile/config/webdav/resolver/WebDavRedirectViewResolver.java create mode 100644 src/main/java/im/zhaojun/zfile/controller/home/WebDavController.java create mode 100644 src/main/java/im/zhaojun/zfile/model/entity/webdav/WebDavEntity.java create mode 100644 src/main/java/im/zhaojun/zfile/model/entity/webdav/WebDavFile.java create mode 100644 src/main/java/im/zhaojun/zfile/model/entity/webdav/WebDavFolder.java create mode 100644 src/main/java/im/zhaojun/zfile/util/RegexMatchUtils.java diff --git a/pom.xml b/pom.xml index e2cd149..2edd9fa 100644 --- a/pom.xml +++ b/pom.xml @@ -94,6 +94,23 @@ 3.6 + + + io.milton + milton-server-ce + 3.1.1.413 + + + commons-logging + commons-logging + + + json + org.json + + + + org.projectlombok diff --git a/src/main/java/im/zhaojun/zfile/config/ApplicationContextConfigure.java b/src/main/java/im/zhaojun/zfile/config/ApplicationContextConfigure.java new file mode 100644 index 0000000..b60f65d --- /dev/null +++ b/src/main/java/im/zhaojun/zfile/config/ApplicationContextConfigure.java @@ -0,0 +1,36 @@ +package im.zhaojun.zfile.config; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.context.annotation.Configuration; + +/** + * 应用上下文配置 + * + * @author me + * @date 2022/4/9 + */ +@Configuration +public class ApplicationContextConfigure implements ApplicationContextAware { + private static ApplicationContext applicationContext; + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + ApplicationContextConfigure.applicationContext = applicationContext; + } + + /** + * bean名称获取对象 + */ + public static Object getBean(String name) throws BeansException { + return applicationContext.getBean(name); + } + + /** + * bean类型获取对象 + */ + public static T getBean(Class clazz) throws BeansException { + return applicationContext.getBean(clazz); + } +} \ No newline at end of file diff --git a/src/main/java/im/zhaojun/zfile/config/webdav/MiltonConfiguration.java b/src/main/java/im/zhaojun/zfile/config/webdav/MiltonConfiguration.java new file mode 100644 index 0000000..309c670 --- /dev/null +++ b/src/main/java/im/zhaojun/zfile/config/webdav/MiltonConfiguration.java @@ -0,0 +1,60 @@ +package im.zhaojun.zfile.config.webdav; + +import im.zhaojun.zfile.config.webdav.adapter.WebDavUrlAdapterImpl; +import im.zhaojun.zfile.config.webdav.auth.SystemConfigSecurityManager; +import im.zhaojun.zfile.config.webdav.resolver.WebDavRedirectViewResolver; +import im.zhaojun.zfile.model.constant.ZFileConstant; +import im.zhaojun.zfile.model.dto.SystemConfigDTO; +import im.zhaojun.zfile.service.SystemConfigService; +import io.milton.http.ResourceFactory; +import io.milton.http.SecurityManager; +import io.milton.http.annotated.AnnotationResourceFactory; +import io.milton.http.fs.NullSecurityManager; +import io.milton.servlet.DefaultMiltonConfigurator; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.context.annotation.Configuration; + +import javax.annotation.Resource; + +/** + * Milton(webDav)配置 + * + * @author me + * @date 2022/4/9 + */ +@Configuration +public class MiltonConfiguration extends DefaultMiltonConfigurator implements InitializingBean { + /** + * 安全管理器 + */ + private static SecurityManager securityManager = new NullSecurityManager(); + + @Resource + private SystemConfigService systemConfigService; + + /** + * 构建milton初始化配置 + */ + @Override + protected void build() { + builder.setSecurityManager(securityManager); + builder.setContextPath(ZFileConstant.WEB_DAV_PREFIX); + builder.setUrlAdapter(new WebDavUrlAdapterImpl()); + final ResourceFactory resourceFactory = builder.getResourceFactory(); + if (resourceFactory instanceof AnnotationResourceFactory) { + ((AnnotationResourceFactory) resourceFactory).setViewResolver(new WebDavRedirectViewResolver()); + } + super.build(); + } + + /** + * 属性初始化完成后,更新安全管理器,使用系统配置鉴权 + */ + @Override + public void afterPropertiesSet() throws Exception { + final SystemConfigDTO systemConfig = systemConfigService.getSystemConfig(); + if (systemConfig != null) { + securityManager = new SystemConfigSecurityManager(systemConfig); + } + } +} diff --git a/src/main/java/im/zhaojun/zfile/config/webdav/WebDavConfiguration.java b/src/main/java/im/zhaojun/zfile/config/webdav/WebDavConfiguration.java new file mode 100644 index 0000000..3887f23 --- /dev/null +++ b/src/main/java/im/zhaojun/zfile/config/webdav/WebDavConfiguration.java @@ -0,0 +1,33 @@ +package im.zhaojun.zfile.config.webdav; + +import im.zhaojun.zfile.model.constant.ZFileConstant; +import io.milton.http.annotated.AnnotationResourceFactory; +import io.milton.servlet.MiltonFilter; +import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * WebDav配置 + * + * @author me + * @date 2022/4/9 + */ +@Configuration +public class WebDavConfiguration { + + @Bean + public FilterRegistrationBean miltonFilter() { + FilterRegistrationBean registration = new FilterRegistrationBean(); + registration.setFilter(new MiltonFilter()); + registration.setName("miltonFilter"); + registration.addUrlPatterns(ZFileConstant.WEB_DAV_PREFIX + "/*"); + registration.addInitParameter("resource.factory.class", AnnotationResourceFactory.class.getName()); + registration.addInitParameter("milton.configurator", MiltonConfiguration.class.getName()); + registration.addInitParameter("controllerPackagesToScan", "im.zhaojun.zfile.controller.home"); + registration.setOrder(1); + return registration; + } + + +} diff --git a/src/main/java/im/zhaojun/zfile/config/webdav/adapter/WebDavUrlAdapterImpl.java b/src/main/java/im/zhaojun/zfile/config/webdav/adapter/WebDavUrlAdapterImpl.java new file mode 100644 index 0000000..bc81d67 --- /dev/null +++ b/src/main/java/im/zhaojun/zfile/config/webdav/adapter/WebDavUrlAdapterImpl.java @@ -0,0 +1,41 @@ + +package im.zhaojun.zfile.config.webdav.adapter; + +import im.zhaojun.zfile.model.constant.ZFileConstant; +import im.zhaojun.zfile.util.RegexMatchUtils; +import io.milton.http.HttpManager; +import io.milton.http.Request; +import io.milton.http.UrlAdapter; + +import java.util.regex.Matcher; + +/** + * WebDav路径适配器实现 + * + * @author me + * @date 2022/4/10 + */ +public class WebDavUrlAdapterImpl implements UrlAdapter { + + /** + * 获取url + * eg: domain.com/{webdavPrefix}/{driveId}/{folders} + * + * @param request 请求 + * @return {@link String} + */ + @Override + public String getUrl(Request request) { + // 匹配url前缀和驱动器ID + Matcher matcher = RegexMatchUtils.match("^" + ZFileConstant.WEB_DAV_PREFIX + "/(\\d+?)(.*)", + HttpManager.decodeUrl(request.getAbsolutePath())); + final String driveId = RegexMatchUtils.getIndexResult(matcher, 1); + if (driveId == null) { + return ""; + } + // 获取摘除前缀和驱动器ID后的文件路径 + final String realPath = RegexMatchUtils.getIndexResult(matcher, 2); + return realPath != null ? realPath : ""; + } + +} diff --git a/src/main/java/im/zhaojun/zfile/config/webdav/auth/SystemConfigSecurityManager.java b/src/main/java/im/zhaojun/zfile/config/webdav/auth/SystemConfigSecurityManager.java new file mode 100644 index 0000000..5e528fc --- /dev/null +++ b/src/main/java/im/zhaojun/zfile/config/webdav/auth/SystemConfigSecurityManager.java @@ -0,0 +1,130 @@ + +package im.zhaojun.zfile.config.webdav.auth; + +import cn.hutool.core.map.MapUtil; +import cn.hutool.crypto.SecureUtil; +import im.zhaojun.zfile.model.dto.SystemConfigDTO; +import io.milton.http.Auth; +import io.milton.http.Request; +import io.milton.http.Request.Method; +import io.milton.http.http11.auth.DigestResponse; +import io.milton.resource.Resource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Map; + +/** + * 基于当前系统配置的WebDav鉴权管理器 + * + * @author me + * @date 2022/4/10 + * @see io.milton.http.fs.SimpleSecurityManager + */ +public class SystemConfigSecurityManager implements io.milton.http.SecurityManager { + + private static final Logger log = LoggerFactory.getLogger(SystemConfigSecurityManager.class); + + private String realm = "SystemConfig"; + private Map nameAndPasswords; + + /** + * 根据系统配置创建安全管理器 + * + * @param systemConfig 系统配置DTO + */ + public SystemConfigSecurityManager(SystemConfigDTO systemConfig) { + if (systemConfig != null) { + this.nameAndPasswords = MapUtil.of(systemConfig.getUsername(), systemConfig.getPassword()); + } + } + + public Object getUserByName(String name) { + String actualPassword = nameAndPasswords.get(name); + if (actualPassword != null) { + return name; + } + return null; + } + + /** + * 用户名+密码身份验证 + * + * @param user 用户 + * @param password 密码 + * @return {@link Object} + */ + @Override + public Object authenticate(String user, String password) { + if (user.contains("@")) { + user = user.substring(0, user.indexOf("@")); + } + String actualPassword = nameAndPasswords.get(user); + if (actualPassword == null) { + log.debug("user not found: " + user); + return null; + } else { + //比对密码MD5摘要 + return (actualPassword.equals(SecureUtil.md5(password))) ? user : null; + } + } + + /** + * 请求摘要身份验证(不进行换算) + * + * @param digestRequest 消化的请求 + * @return {@link Object} + */ + @Override + public Object authenticate(DigestResponse digestRequest) { + String serverResponse = nameAndPasswords.get(digestRequest.getUser()); + String clientResponse = digestRequest.getResponseDigest(); + //比对密码MD5摘要 + if (serverResponse.equals(SecureUtil.md5(clientResponse))) { + return "ok"; + } else { + return null; + } + } + + @Override + public boolean authorise(Request request, Method method, Auth auth, Resource resource) { + if (auth == null) { + log.trace("authorise: declining because there is no auth object"); + return false; + } else { + if (auth.getTag() == null) { + log.trace("authorise: declining because there is no auth.getTag() object"); + return false; + } else { + log.trace("authorise: permitting because there is an authenticated user associated with this request"); + return true; + } + } + } + + @Override + public String getRealm(String host) { + return realm; + } + + /** + * @param realm the realm to set + */ + public void setRealm(String realm) { + this.realm = realm; + } + + public void setNameAndPasswords(Map nameAndPasswords) { + this.nameAndPasswords = nameAndPasswords; + } + + + @Override + public boolean isDigestAllowed() { + // 关闭请求摘要换算,client端请求时若换算为摘要,则无法和系统设置中获取的密码MD5比对 + return false; + } + +} + diff --git a/src/main/java/im/zhaojun/zfile/config/webdav/resolver/WebDavRedirectViewResolver.java b/src/main/java/im/zhaojun/zfile/config/webdav/resolver/WebDavRedirectViewResolver.java new file mode 100644 index 0000000..a849791 --- /dev/null +++ b/src/main/java/im/zhaojun/zfile/config/webdav/resolver/WebDavRedirectViewResolver.java @@ -0,0 +1,62 @@ + +package im.zhaojun.zfile.config.webdav.resolver; + +import cn.hutool.core.util.URLUtil; +import im.zhaojun.zfile.model.constant.ZFileConstant; +import im.zhaojun.zfile.model.entity.webdav.WebDavFile; +import io.milton.common.View; +import io.milton.http.template.TemplateProcessor; +import io.milton.http.template.ViewResolver; +import io.milton.servlet.OutputStreamWrappingHttpServletResponse; +import io.milton.servlet.ServletResponse; + +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.OutputStream; +import java.util.Map; + +/** + * WebDav重定向视图处理器 + * Get注解handler返回字符串时,将使用本ViewResolver处理 + * + * @author me + * @date 2022/4/9 + */ +public class WebDavRedirectViewResolver implements ViewResolver { + + @Override + public TemplateProcessor resolveView(View view) { + return new RedirectTemplateProcessor(); + } + + /** + * 重定向模板处理程序 + * + * @author me + * @date 2022/04/10 + */ + public static class RedirectTemplateProcessor implements TemplateProcessor { + + @Override + public void execute(Map model, OutputStream out) { + try { + // 获取要下载的资源文件 + final Object resource = model.get("resource"); + if (!(resource instanceof WebDavFile)) { + throw new RuntimeException("couldn't get direct url."); + } + final WebDavFile file = (WebDavFile) resource; + // 构造文件直链的路径 + final String redirectPath = String.format("/%s/%s%s", ZFileConstant.DIRECT_LINK_PREFIX, file.getDriveId(), file.getFullPath()); + // 重定向到直链 + HttpServletResponse resp = new OutputStreamWrappingHttpServletResponse(ServletResponse.getResponse(), out); + resp.setStatus(301); + resp.setHeader("Location", URLUtil.encode(redirectPath)); + resp.setHeader("Connection", "close"); + resp.flushBuffer(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + } +} diff --git a/src/main/java/im/zhaojun/zfile/controller/home/WebDavController.java b/src/main/java/im/zhaojun/zfile/controller/home/WebDavController.java new file mode 100644 index 0000000..8ec1a1a --- /dev/null +++ b/src/main/java/im/zhaojun/zfile/controller/home/WebDavController.java @@ -0,0 +1,157 @@ +package im.zhaojun.zfile.controller.home; + +import com.alibaba.fastjson.JSON; +import im.zhaojun.zfile.config.ApplicationContextConfigure; +import im.zhaojun.zfile.context.DriveContext; +import im.zhaojun.zfile.model.constant.ZFileConstant; +import im.zhaojun.zfile.model.dto.FileItemDTO; +import im.zhaojun.zfile.model.entity.webdav.WebDavEntity; +import im.zhaojun.zfile.model.entity.webdav.WebDavFile; +import im.zhaojun.zfile.model.entity.webdav.WebDavFolder; +import im.zhaojun.zfile.service.base.AbstractBaseFileService; +import im.zhaojun.zfile.util.RegexMatchUtils; +import io.milton.annotations.*; +import io.milton.http.HttpManager; +import lombok.extern.slf4j.Slf4j; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Collections; +import java.util.Date; +import java.util.List; + +/** + * WebDav控制器 + * + * @author me + * @date 2022/4/9 + */ +@Slf4j +@ResourceController +public class WebDavController { + private static final Logger LOGGER = LoggerFactory.getLogger(WebDavController.class); + + + /** + * 获取根目录文件夹 + * + * @return {@link WebDavFolder} WebDav文件夹 + */ + @Root + public WebDavFolder getRootFolder() { + return new WebDavFolder(ZFileConstant.PATH_SEPARATOR, getDriveId()); + } + + /** + * 获取根目录子文件/文件夹(控制器) + * + * @param rootFolder 根文件夹 + * @return {@link WebDavController} 根控制器 + */ + @ChildrenOf + public WebDavController getChildren(WebDavController rootFolder) { + return this; + } + + /** + * 获取子文件/文件夹 + * + * @param parent 父文件夹 + * @return {@link List}<{@link WebDavEntity}> WebDav实体 + */ + @ChildrenOf + public List getChildren(WebDavFolder parent) { + if (parent == null) { + return Collections.emptyList(); + } + try { + // 获取驱动器文件服务 + AbstractBaseFileService fileService = ApplicationContextConfigure.getBean(DriveContext.class).get(parent.getDriveId()); + if (fileService == null) { + return Collections.emptyList(); + } + // 获取文件列表 + List fileItemList = fileService.fileList(parent.getFullPath()); + // 转换FileItemDTO为WebDavEntity + return WebDavEntity.convertFromFileItemDTO(fileItemList, parent); + } catch (Exception e) { + LOGGER.warn("get webDav children failed,parent:{},msg:{}", JSON.toJSONString(parent), e.getMessage(), e); + return Collections.emptyList(); + } + } + + /** + * 获取子文件内容 + * + * @param webDavFile WebDav文件 + * @return {@link String} ViewResolver模板名称 + */ + @Get + public String getChild(WebDavFile webDavFile) { + return JSON.toJSONString(webDavFile); + } + + /** + * 获取WebDav实体文件名 + */ + @Name + public String getWebDavFile(WebDavEntity webDavEntity) { + return webDavEntity.getName(); + } + + /** + * 获取WebDav实体展示名称 + */ + @DisplayName + public String getDisplayName(WebDavEntity webDavEntity) { + return webDavEntity.getName(); + } + + /** + * 获取WebDav实体唯一id + */ + @UniqueId + public String getUniqueId(WebDavEntity entity) { + return entity.getId().toString(); + } + + /** + * 获取WebDav实体修改日期 + */ + @ModifiedDate + public Date getModifiedDate(WebDavEntity webDavEntity) { + return webDavEntity.getModifiedDate(); + } + + /** + * 获取WebDav实体创建日期 + */ + @CreatedDate + public Date getCreatedDate(WebDavEntity webDavEntity) { + return webDavEntity.getCreatedDate(); + } + + /** + * 获取WebDav实体大小 + */ + @ContentLength + public Long getContentLength(WebDavEntity entity) { + if (entity instanceof WebDavFile) { + return ((WebDavFile) entity).getSize(); + } + // 性能考虑,文件夹暂不进行大小统计 + return null; + } + + + /** + * 获取驱动器id + * + * @return {@link Integer} + */ + private Integer getDriveId() { + String requestUrl = HttpManager.decodeUrl(HttpManager.request().getAbsolutePath()); + final String driveId = RegexMatchUtils.matchByIndex("^" + ZFileConstant.WEB_DAV_PREFIX + "/(\\d+?)(.*)", requestUrl, 1); + return driveId != null ? Integer.valueOf(driveId) : null; + } +} \ No newline at end of file diff --git a/src/main/java/im/zhaojun/zfile/model/constant/ZFileConstant.java b/src/main/java/im/zhaojun/zfile/model/constant/ZFileConstant.java index 7045b33..6f63446 100644 --- a/src/main/java/im/zhaojun/zfile/model/constant/ZFileConstant.java +++ b/src/main/java/im/zhaojun/zfile/model/constant/ZFileConstant.java @@ -21,6 +21,11 @@ public class ZFileConstant { */ public static String DIRECT_LINK_PREFIX = "directlink"; + /** + * WebDav前缀 + */ + public static String WEB_DAV_PREFIX = "/webdav"; + /** * 系统产生的临时文件路径 */ diff --git a/src/main/java/im/zhaojun/zfile/model/entity/webdav/WebDavEntity.java b/src/main/java/im/zhaojun/zfile/model/entity/webdav/WebDavEntity.java new file mode 100644 index 0000000..94491a1 --- /dev/null +++ b/src/main/java/im/zhaojun/zfile/model/entity/webdav/WebDavEntity.java @@ -0,0 +1,112 @@ +package im.zhaojun.zfile.model.entity.webdav; + +import im.zhaojun.zfile.model.constant.ZFileConstant; +import im.zhaojun.zfile.model.dto.FileItemDTO; +import im.zhaojun.zfile.model.enums.FileTypeEnum; +import im.zhaojun.zfile.util.StringUtils; +import lombok.Data; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.UUID; + +/** + * WebDav实体 + * + * @author me + * @date 2022/4/9 + */ +@Data +public class WebDavEntity { + /** + * 唯一ID + */ + private UUID id; + /** + * 驱动器ID + */ + private Integer driveId; + /** + * 名称 + */ + private String name; + /** + * 创建时间 + */ + private Date createdDate; + /** + * 修改时间 + */ + private Date modifiedDate; + /** + * 是否是目录 + */ + private boolean isDirectory; + /** + * 父文件夹 + */ + private WebDavFolder parent; + + public WebDavEntity() { + } + + public WebDavEntity(String name, WebDavFolder parent) { + this.id = UUID.randomUUID(); + this.name = name; + this.parent = parent; + this.createdDate = new Date(); + this.modifiedDate = new Date(); + this.isDirectory = true; + } + + public WebDavEntity(UUID id, String name, Date createdDate, Date modifiedDate, + WebDavFolder parent) { + this.id = id; + this.name = name; + this.parent = parent; + this.createdDate = createdDate; + this.modifiedDate = modifiedDate; + this.isDirectory = true; + } + + /** + * 获取全路径 + */ + public String getFullPath() { + if (this.getParent() != null) { + final String parentFullPath = this.getParent().getFullPath(); + return StringUtils.removeDuplicateSeparator(parentFullPath + ZFileConstant.PATH_SEPARATOR + this.getName()); + } else { + return ZFileConstant.PATH_SEPARATOR; + } + } + + public static List convertFromFileItemDTO(List fileItemList, WebDavFolder parent) { + List result = new ArrayList<>(); + if (fileItemList == null || fileItemList.size() == 0) { + return result; + } + for (FileItemDTO each : fileItemList) { + WebDavEntity entity = convertFromFileItemDTO(each, parent); + result.add(entity); + } + return result; + } + + public static WebDavEntity convertFromFileItemDTO(FileItemDTO fileItemDTO, WebDavFolder parent) { + if (fileItemDTO == null) { + return null; + } + WebDavEntity entity; + if (fileItemDTO.getType() == FileTypeEnum.FOLDER) { + entity = new WebDavFolder(fileItemDTO.getName(), parent); + } else { + entity = new WebDavFile(fileItemDTO.getName(), fileItemDTO.getSize(), parent); + } + entity.setModifiedDate(fileItemDTO.getTime()); + entity.setDriveId(parent.getDriveId()); + return entity; + } + +} diff --git a/src/main/java/im/zhaojun/zfile/model/entity/webdav/WebDavFile.java b/src/main/java/im/zhaojun/zfile/model/entity/webdav/WebDavFile.java new file mode 100644 index 0000000..dcaba60 --- /dev/null +++ b/src/main/java/im/zhaojun/zfile/model/entity/webdav/WebDavFile.java @@ -0,0 +1,37 @@ +package im.zhaojun.zfile.model.entity.webdav; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.Date; +import java.util.UUID; + +/** + * WebDav文件实体 + * + * @author me + * @date 2022/4/9 + */ +@EqualsAndHashCode(callSuper = true) +@Data +public class WebDavFile extends WebDavEntity { + /** + * 大小 + */ + private Long size; + /** + * 内容类型 + */ + private String contentType; + + public WebDavFile(String fileName, Long size, WebDavFolder parent) { + super(fileName, parent); + this.setSize(size); + this.setDirectory(false); + } + + public WebDavFile(UUID id, String name, Date createdDate, Date modifiedDate, WebDavFolder parent) { + super(id, name, createdDate, modifiedDate, parent); + this.setDirectory(false); + } +} diff --git a/src/main/java/im/zhaojun/zfile/model/entity/webdav/WebDavFolder.java b/src/main/java/im/zhaojun/zfile/model/entity/webdav/WebDavFolder.java new file mode 100644 index 0000000..5513216 --- /dev/null +++ b/src/main/java/im/zhaojun/zfile/model/entity/webdav/WebDavFolder.java @@ -0,0 +1,41 @@ +package im.zhaojun.zfile.model.entity.webdav; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.Date; +import java.util.UUID; + +/** + * WebDav文件夹实体 + * + * @author me + * @date 2022/4/9 + */ +@EqualsAndHashCode(callSuper = true) +@Data +public class WebDavFolder extends WebDavEntity { + public WebDavFolder(String folderName, WebDavFolder parent) { + super(folderName, parent); + } + + public WebDavFolder(String folderName, Integer driveId) { + super(folderName, null); + setDriveId(driveId); + } + + public WebDavFolder(UUID id, String name, Date createdDate, Date modifiedDate, WebDavFolder parent) { + super(id, name, createdDate, modifiedDate, parent); + } + + public WebDavFile addFile(String fileName, Long size) { + WebDavFile file = new WebDavFile(fileName, size, this); + file.setDirectory(false); + return file; + } + + public WebDavFolder addFolder(String folderName) { + return new WebDavFolder(folderName, this); + } + +} diff --git a/src/main/java/im/zhaojun/zfile/util/RegexMatchUtils.java b/src/main/java/im/zhaojun/zfile/util/RegexMatchUtils.java new file mode 100644 index 0000000..6e3b79f --- /dev/null +++ b/src/main/java/im/zhaojun/zfile/util/RegexMatchUtils.java @@ -0,0 +1,61 @@ +package im.zhaojun.zfile.util; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * 正则匹配工具类 + * + * @author me + * @date 2022/4/9 + */ +public class RegexMatchUtils { + + /** + * 正则匹配分组序号值 + * + * @param regex 正则表达式 + * @param str 待匹配字符串 + * @param index 分组序号,从1开始 + * @return {@link String} 不存在/匹配失败返回null + */ + public static String matchByIndex(String regex, String str, Integer index) { + Matcher matcher = match(regex, str); + if (matcher == null) { + return null; + } + return getIndexResult(matcher, index); + } + + /** + * 匹配字符串 + * + * @param regex 正则表达式 + * @param str 待匹配字符串 + * @return {@link Matcher} + */ + public static Matcher match(String regex, String str) { + if (str == null || "".equals(str)) { + return null; + } + Matcher matcher = Pattern.compile(regex).matcher(str); + if (!matcher.lookingAt()) { + return null; + } + return matcher; + } + + /** + * 获取指定分组序号的匹配结果 + * + * @param matcher {@link Matcher} + * @param index 分组序号,从1开始 + * @return {@link String} 不存在/匹配失败返回null + */ + public static String getIndexResult(Matcher matcher, Integer index) { + if (matcher == null || index == null || index < 0 || index > matcher.groupCount()) { + return null; + } + return matcher.group(index); + } +}