mirror of
https://github.com/zfile-dev/zfile.git
synced 2025-04-19 05:34:52 +00:00
Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4dd6cdb4b3 | ||
|
|
c6127c029f | ||
|
|
e149039ecb | ||
|
|
37688d83cf | ||
|
|
6692016642 | ||
|
|
3f41aeda9a | ||
|
|
de86d5c47d | ||
|
|
c89e072005 |
19
pom.xml
19
pom.xml
@@ -12,7 +12,7 @@
|
||||
|
||||
<groupId>im.zhaojun</groupId>
|
||||
<artifactId>zfile</artifactId>
|
||||
<version>3.2.2</version>
|
||||
<version>3.2.3</version>
|
||||
<name>zfile</name>
|
||||
<packaging>war</packaging>
|
||||
<description>一个在线的文件浏览系统</description>
|
||||
@@ -94,6 +94,23 @@
|
||||
<version>3.6</version>
|
||||
</dependency>
|
||||
|
||||
<!-- WebDav -->
|
||||
<dependency>
|
||||
<groupId>io.milton</groupId>
|
||||
<artifactId>milton-server-ce</artifactId>
|
||||
<version>3.1.1.413</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
<groupId>commons-logging</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>json</artifactId>
|
||||
<groupId>org.json</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!-- 其他工具类 -->
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
|
||||
@@ -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> T getBean(Class<T> clazz) throws BeansException {
|
||||
return applicationContext.getBean(clazz);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -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 : "";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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<String, String> 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<String, String> nameAndPasswords) {
|
||||
this.nameAndPasswords = nameAndPasswords;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isDigestAllowed() {
|
||||
// 关闭请求摘要换算,client端请求时若换算为摘要,则无法和系统设置中获取的密码MD5比对
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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<String, Object> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
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 org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* WebDav控制器
|
||||
*
|
||||
* @author me
|
||||
* @date 2022/4/9
|
||||
*/
|
||||
@Slf4j
|
||||
@ResourceController
|
||||
@ConditionalOnProperty(value = "webdav.enable", havingValue = "true")
|
||||
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<WebDavEntity> 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<FileItemDTO> 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;
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,11 @@ public class ZFileConstant {
|
||||
*/
|
||||
public static String DIRECT_LINK_PREFIX = "directlink";
|
||||
|
||||
/**
|
||||
* WebDav前缀
|
||||
*/
|
||||
public static String WEB_DAV_PREFIX = "/webdav";
|
||||
|
||||
/**
|
||||
* 系统产生的临时文件路径
|
||||
*/
|
||||
|
||||
@@ -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<WebDavEntity> convertFromFileItemDTO(List<FileItemDTO> fileItemList, WebDavFolder parent) {
|
||||
List<WebDavEntity> 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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
61
src/main/java/im/zhaojun/zfile/util/RegexMatchUtils.java
Normal file
61
src/main/java/im/zhaojun/zfile/util/RegexMatchUtils.java
Normal file
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -97,6 +97,11 @@
|
||||
"type": "java.lang.String",
|
||||
"defaultValue": "directlink",
|
||||
"description": "直链前缀名称, 默认为 directlink"
|
||||
},
|
||||
{
|
||||
"name": "zfile.webdav",
|
||||
"type": "java.lang.Boolean",
|
||||
"description": "是否开启 webdav 文件管理."
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
zfile:
|
||||
debug: false
|
||||
webdav: false
|
||||
directLinkPrefix: directlink
|
||||
log:
|
||||
path: ${user.home}/.zfile/logs
|
||||
@@ -80,4 +81,4 @@ spring:
|
||||
continue-on-error: true
|
||||
mode: always
|
||||
data-locations: classpath*:db/data.sql
|
||||
encoding: utf-8
|
||||
encoding: utf-8
|
||||
@@ -13,4 +13,5 @@ INSERT INTO SYSTEM_CONFIG (`ID`, `k`, `REMARK`, `value`) VALUES (17, 'showAnnoun
|
||||
INSERT INTO SYSTEM_CONFIG (`ID`, `k`, `REMARK`, `value`) VALUES (18, 'layout', '页面布局', 'full');
|
||||
INSERT INTO SYSTEM_CONFIG (`ID`, `k`, `REMARK`, `value`) VALUES (19, 'showLinkBtn', '是否显示生成直链按钮', 'true');
|
||||
INSERT INTO SYSTEM_CONFIG (`ID`, `k`, `REMARK`, `value`) VALUES (20, 'showShortLink', '是否显示短链', 'true');
|
||||
INSERT INTO SYSTEM_CONFIG (`ID`, `k`, `REMARK`, `value`) VALUES (21, 'showPathLink', '是否显示路径直链', 'true');
|
||||
INSERT INTO SYSTEM_CONFIG (`ID`, `k`, `REMARK`, `value`) VALUES (21, 'showPathLink', '是否显示路径直链', 'true');
|
||||
alter table short_link change "key" key varchar(255) null;
|
||||
@@ -76,6 +76,9 @@
|
||||
true: 表示当前logger的appender-ref和rootLogger的appender-ref都有效
|
||||
-->
|
||||
|
||||
<!-- milton webdav -->
|
||||
<logger name="io.milton" additivity="false" level="info"/>
|
||||
|
||||
<!-- jetCache logger -->
|
||||
<logger name="com.alicp" additivity="false" level="debug"/>
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user