Compare commits

..

19 Commits
0.5 ... 0.6

Author SHA1 Message Date
zhaojun1998
f198b34324 🔖 升级版本为 0.6 2020-01-12 11:18:50 +08:00
zhaojun1998
3095e0c8d9 💄 更新页面, 优化缓存页面展示 2020-01-12 11:15:01 +08:00
zhaojun1998
594246127d 🐛 修复更改策略时, 未正确启用和关闭缓存的 BUG 2020-01-12 11:14:20 +08:00
zhaojun1998
f6c5f7a91b 🔧 修改配置配置文件, 将日志改为单独配置 2020-01-12 11:13:02 +08:00
zhaojun1998
2a765fff7e 🐛 获取缓存是否开启时的 NPE 问题 2020-01-11 23:20:12 +08:00
zhaojun1998
28f958878b 🔊 更新日志级别 2020-01-11 23:02:19 +08:00
zhaojun1998
368f3a90eb 移除无用依赖 2020-01-11 22:53:19 +08:00
zhaojun1998
98b14abbfc 🔧 修改配置文件, 去除默认缓存时间. 2020-01-11 22:49:55 +08:00
zhaojun1998
7c04c3d6b8 优化代码结构 2020-01-11 22:48:28 +08:00
zhaojun1998
921cb1a115 通过反射优化代码 2020-01-08 22:34:15 +08:00
zhaojun1998
9371968c3b 增强根据 value 获取枚举的功能 2020-01-08 22:33:30 +08:00
zhaojun1998
47e88849ac 🐛 修复当前存储引擎为空时, 与新设置的存储引擎比较出现的 NPE 2020-01-08 22:32:47 +08:00
zhaojun1998
2f0f41f413 去除无效输出 2020-01-08 21:31:24 +08:00
zhaojun1998
7667765abc 🐛 修复本地存储的文件名, 包含 &?=[] 等特殊字符时出现的问题 2020-01-08 21:28:05 +08:00
zhaojun1998
b2a2e69af5 🔒 关闭 URL 部分校验, 允许中文文件名 2020-01-08 21:22:03 +08:00
zhaojun1998
7c729a72e2 🐛 本地存储, 获取文件不存在返回状态码 404 2020-01-07 22:57:59 +08:00
zhaojun1998
5495abc881 更新未知歌曲默认封面 2020-01-06 23:00:07 +08:00
zhaojun1998
797cd4fc06 💄 更新页面 2020-01-05 16:11:02 +08:00
zhaojun1998
8148d182cf 更新缓存策略刷新时间 2020-01-05 16:01:50 +08:00
41 changed files with 465 additions and 224 deletions

View File

@@ -34,19 +34,19 @@ yum install -y java # 适用于 Centos 7.x
下载项目:
```bash
wget https://github.com/zhaojun1998/zfile/releases/download/0.5/zfile-0.5.jar
wget https://github.com/zhaojun1998/zfile/releases/download/0.6/zfile-0.6.jar
```
启动项目:
```bash
java -Djava.security.egd=file:/dev/./urandom -jar zfile-0.5.jar
java -Djava.security.egd=file:/dev/./urandom -jar zfile-0.6.jar
## 高级启动
java -Djava.security.egd=file:/dev/./urandom -jar zfile-0.5.jar --server.port=18777
java -Djava.security.egd=file:/dev/./urandom -jar zfile-0.6.jar --server.port=18777
## 后台运行
nohup java -Djava.security.egd=file:/dev/./urandom -jar zfile-0.5.jar &
nohup java -Djava.security.egd=file:/dev/./urandom -jar zfile-0.6.jar &
```
> 系统使用的是内置配置文件, 默认配置请参考: [application.yml](https://github.com/zhaojun1998/zfile/blob/master/src/main/resources/application.yml)
@@ -57,13 +57,6 @@ nohup java -Djava.security.egd=file:/dev/./urandom -jar zfile-0.5.jar &
> *指定 `-Djava.security.egd=file:/dev/./urandom` 是为了防止在 Linux 环境中, 生成首次登陆生成 sessionId 取系统随机数过慢的问题.*
重要参数:
- `server.port` 为指定端口, 默认为 `8080`
- `logging.path` 为日志文件存放路径, 默认为 `${user.home}/.zfile/logs`
- `spring.datasource` 下配置了 `h2``mysql` 两种数据库的支持, 默认采用 `h2`.
- `spring.cache.type` 为指定缓存方式, 默认为 `caffeine`, 即内存缓存, 无需安装, 支持切换为 `redis`, 但需配置 `spring.redis.host``spring.redis.password` 参数后才可使用.
访问地址:
用户前台: http://127.0.0.1:8080/#/main
@@ -85,12 +78,10 @@ nohup java -Djava.security.egd=file:/dev/./urandom -jar zfile-0.5.jar &
缓存默认支持 `h2``mysql`, 前者为嵌入式数据库, 无需安装, 但后者相对性能更好.
### 默认路径
默认 H2 数据库文件地址: `~/.zfile/db/`, `~` 表示用户目录, windows 为 `C:/Users/用户名/`, linux 为 `/home/用户名/`, root 用户为 `/root/`
### 头尾文件和加密文件
- 目录头部显示文件名为 `header.md`

18
pom.xml
View File

@@ -12,7 +12,7 @@
<groupId>im.zhaojun</groupId>
<artifactId>zfile</artifactId>
<version>0.5</version>
<version>0.6</version>
<name>zfile</name>
<description>一个在线的文件浏览系统</description>
@@ -65,7 +65,7 @@
<version>4.5.11</version>
</dependency>
<!-- 存储引擎相关 API, 对象存储、FTP、 Rest API-->
<!-- 存储策略相关 API, 对象存储、FTP、 Rest API-->
<dependency>
<groupId>com.upyun</groupId>
<artifactId>java-sdk</artifactId>
@@ -104,6 +104,20 @@
<groupId>com.alicp.jetcache</groupId>
<artifactId>jetcache-starter-redis</artifactId>
<version>2.5.14</version>
<exclusions>
<exclusion>
<groupId>com.alicp.jetcache</groupId>
<artifactId>jetcache-redis</artifactId>
</exclusion>
<exclusion>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</exclusion>
<exclusion>
<groupId>com.esotericsoftware</groupId>
<artifactId>kryo</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>

View File

@@ -37,6 +37,7 @@ public class AliyunServiceImpl extends AbstractS3FileService implements FileServ
super.basePath = stringStorageConfigMap.get(StorageConfigConstant.BASE_PATH).getValue();
if (Objects.isNull(accessKey) || Objects.isNull(secretKey) || Objects.isNull(endPoint) || Objects.isNull(bucketName)) {
log.debug("初始化存储策略 [{}] 失败: 参数不完整", getStorageTypeEnum().getDescription());
isInitialized = false;
} else {
BasicAWSCredentials credentials = new BasicAWSCredentials(accessKey, secretKey);

View File

@@ -1,7 +1,6 @@
package im.zhaojun.common.controller;
import im.zhaojun.common.model.StorageConfig;
import im.zhaojun.common.model.dto.CacheConfigDTO;
import im.zhaojun.common.model.dto.ResultBean;
import im.zhaojun.common.model.dto.SystemConfigDTO;
import im.zhaojun.common.model.enums.StorageTypeEnum;
@@ -14,11 +13,13 @@ import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.List;
import java.util.Set;
import java.util.Map;
import java.util.Objects;
/**
* 后台管理
@@ -58,7 +59,8 @@ public class AdminController {
systemConfigDTO.setId(1);
systemConfigService.updateSystemConfig(systemConfigDTO);
if (!currentStorageStrategy.equals(systemConfigDTO.getStorageStrategy())) {
if (!Objects.equals(currentStorageStrategy, systemConfigDTO.getStorageStrategy())) {
log.info("已将存储策略由 {} 切换为 {}", currentStorageStrategy, systemConfigDTO.getStorageStrategy());
refreshStorageStrategy();
}
@@ -75,8 +77,8 @@ public class AdminController {
}
/**
* 获取指定存储引擎的设置
* @param storageType 存储引擎
* 获取指定存储策略的设置
* @param storageType 存储策略
* @return 所有设置
*/
@GetMapping("/strategy-form")
@@ -85,38 +87,36 @@ public class AdminController {
return ResultBean.success(storageConfigList);
}
@GetMapping("/cache/config")
public ResultBean cacheConfig() throws Exception {
AbstractFileService fileService = systemConfigService.getCurrentFileService();
Set<String> cacheKeys = fileService.getCacheKeys();
CacheConfigDTO cacheConfigDTO = new CacheConfigDTO();
cacheConfigDTO.setEnableCache(systemConfigService.getEnableCache());
cacheConfigDTO.setCacheFinish(fileAsyncCacheService.isCacheFinish());
cacheConfigDTO.setCacheKeys(cacheKeys);
/**
* 保存存储策略
* @param storageStrategyConfig 保存表单值
* @param storageStrategy 所属策略
* @return 操作结果
* @throws Exception 表单解析出错异常
*/
@PostMapping("/storage-strategy")
public ResultBean save(@RequestParam Map<String, String> storageStrategyConfig, StorageTypeEnum storageStrategy) throws Exception {
List<StorageConfig> storageConfigList = storageConfigService.selectStorageConfigByType(storageStrategy);
for (StorageConfig storageConfig : storageConfigList) {
String key = storageConfig.getKey();
String value = storageStrategyConfig.get(key);
storageConfig.setValue(value);
}
storageConfigService.updateStorageConfig(storageConfigList);
return ResultBean.success(cacheConfigDTO);
}
StorageTypeEnum currentStorageStrategy = systemConfigService.getCurrentStorageStrategy();
if (Objects.equals(storageStrategy, currentStorageStrategy)) {
if (log.isDebugEnabled()) {
log.debug("检测到更新了当前启用的存储策略 {}, 已清理缓存.", currentStorageStrategy);
}
@PostMapping("/cache/refresh")
public ResultBean refreshCache(String key) throws Exception {
AbstractFileService fileService = systemConfigService.getCurrentFileService();
fileService.refreshCache(key);
return ResultBean.success();
}
AbstractFileService fileService = systemConfigService.getCurrentFileService();
fileService.clearFileCache();
fileService.init();
fileAsyncCacheService.cacheGlobalFile();
}
@PostMapping("/cache/clear")
public ResultBean clearCache(String key) throws Exception {
AbstractFileService fileService = systemConfigService.getCurrentFileService();
fileService.clearCache();
return ResultBean.success();
}
@PostMapping("/cache/all")
public ResultBean cacheAll() throws Exception {
AbstractFileService fileService = systemConfigService.getCurrentFileService();
fileService.clearCache();
fileAsyncCacheService.cacheGlobalFile();
return ResultBean.success();
}
@@ -137,9 +137,8 @@ public class AdminController {
} else {
AbstractFileService fileService = systemConfigService.getCurrentFileService();
fileService.init();
log.info("当前启用存储类型: {}", storageStrategy.getDescription());
log.info("切换至存储类型: {}", storageStrategy.getDescription());
// if 判断是否开启搜索.
fileAsyncCacheService.cacheGlobalFile();
}
}

View File

@@ -0,0 +1,82 @@
package im.zhaojun.common.controller;
import im.zhaojun.common.model.dto.CacheConfigDTO;
import im.zhaojun.common.model.dto.ResultBean;
import im.zhaojun.common.service.AbstractFileService;
import im.zhaojun.common.service.FileAsyncCacheService;
import im.zhaojun.common.service.FileCacheService;
import im.zhaojun.common.service.SystemConfigService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.Set;
/**
* @author zhaojun
* @date 2020/1/11 14:03
*/
@RestController
@RequestMapping("/admin/cache")
public class CacheController {
@Resource
private SystemConfigService systemConfigService;
@Resource
private FileAsyncCacheService fileAsyncCacheService;
@Resource
private FileCacheService fileCacheService;
@PostMapping("/enable")
public ResultBean enableCache() throws Exception {
fileCacheService.enableCache();
return ResultBean.success();
}
@PostMapping("/disable")
public ResultBean disableCache() throws Exception {
fileCacheService.disableCache();
return ResultBean.success();
}
@GetMapping("/config")
public ResultBean cacheConfig() throws Exception {
AbstractFileService fileService = systemConfigService.getCurrentFileService();
Set<String> cacheKeys = fileService.getCacheKeys();
CacheConfigDTO cacheConfigDTO = new CacheConfigDTO();
cacheConfigDTO.setEnableCache(systemConfigService.getEnableCache());
cacheConfigDTO.setCacheFinish(fileAsyncCacheService.isCacheFinish());
cacheConfigDTO.setCacheKeys(cacheKeys);
cacheConfigDTO.setCacheDirectoryCount(fileAsyncCacheService.getCacheDirectoryCount());
cacheConfigDTO.setCacheFileCount(fileAsyncCacheService.getCacheFileCount());
return ResultBean.success(cacheConfigDTO);
}
@PostMapping("/refresh")
public ResultBean refreshCache(String key) throws Exception {
AbstractFileService fileService = systemConfigService.getCurrentFileService();
fileService.refreshCache(key);
return ResultBean.success();
}
@PostMapping("/clear")
public ResultBean clearCache(String key) throws Exception {
AbstractFileService fileService = systemConfigService.getCurrentFileService();
fileService.clearFileCache();
fileAsyncCacheService.resetCacheCount();
return ResultBean.success();
}
@PostMapping("/all")
public ResultBean cacheAll() throws Exception {
AbstractFileService fileService = systemConfigService.getCurrentFileService();
fileService.clearFileCache();
fileAsyncCacheService.cacheGlobalFile();
return ResultBean.success();
}
}

View File

@@ -3,13 +3,11 @@ package im.zhaojun.common.controller;
import cn.hutool.core.util.URLUtil;
import im.zhaojun.common.annotation.CheckStorageStrategyInit;
import im.zhaojun.common.exception.SearchDisableException;
import im.zhaojun.common.model.StorageConfig;
import im.zhaojun.common.model.constant.ZFileConstant;
import im.zhaojun.common.model.dto.FileItemDTO;
import im.zhaojun.common.model.dto.ResultBean;
import im.zhaojun.common.model.dto.SiteConfigDTO;
import im.zhaojun.common.model.dto.SystemConfigDTO;
import im.zhaojun.common.model.enums.StorageTypeEnum;
import im.zhaojun.common.service.AbstractFileService;
import im.zhaojun.common.service.FileAsyncCacheService;
import im.zhaojun.common.service.StorageConfigService;
@@ -90,6 +88,7 @@ public class FileController {
return ResultBean.successData(fileSubItem);
}
/**
* 获取文件类容, 仅限用于, txt, md, ini 等普通文本文件.
* @param url 文件路径
@@ -111,6 +110,7 @@ public class FileController {
return HttpUtil.getTextContent(url);
}
/**
* 检测文件是否存在
* @param url 文件路径
@@ -121,6 +121,7 @@ public class FileController {
return HttpUtil.checkUrlExist(url);
}
/**
* 获取系统配置信息和当前页的标题, 文件头, 文件尾信息
* @param path 路径
@@ -133,15 +134,6 @@ public class FileController {
return ResultBean.successData(config);
}
@CheckStorageStrategyInit
@GetMapping("/clearCache")
public ResultBean clearCache() throws Exception {
AbstractFileService fileService = systemConfigService.getCurrentFileService();
if (fileService != null) {
fileService.clearCache();
}
return ResultBean.success();
}
@CheckStorageStrategyInit
@GetMapping("/audioInfo")
@@ -149,6 +141,7 @@ public class FileController {
return ResultBean.success(AudioHelper.getAudioInfo(url));
}
@CheckStorageStrategyInit
@GetMapping("/search")
public ResultBean search(@RequestParam(value = "name", defaultValue = "/") String name) throws Exception {
@@ -163,13 +156,6 @@ public class FileController {
return ResultBean.success(fileService.search(URLUtil.decode(name)));
}
@GetMapping("/form")
public ResultBean getFormByStorageType(String storageType) {
StorageTypeEnum storageTypeEnum = StorageTypeEnum.getEnum(storageType);
List<StorageConfig> storageConfigList = storageConfigService.selectStorageConfigByType(storageTypeEnum);
storageConfigList.forEach(storageConfig -> storageConfig.setValue(null));
return ResultBean.success(storageConfigList);
}
/**
* 过滤文件列表, 不显示密码, 头部和尾部文件.

View File

@@ -6,26 +6,22 @@ import im.zhaojun.common.model.dto.InstallModelDTO;
import im.zhaojun.common.model.dto.ResultBean;
import im.zhaojun.common.model.dto.SystemConfigDTO;
import im.zhaojun.common.model.enums.StorageTypeEnum;
import im.zhaojun.common.service.AbstractFileService;
import im.zhaojun.common.service.FileAsyncCacheService;
import im.zhaojun.common.service.StorageConfigService;
import im.zhaojun.common.service.SystemConfigService;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.Objects;
/**
* 系统安装初始化
* @author zhaojun
*/
@Controller
@RestController
public class InstallController {
@Resource
@@ -41,7 +37,6 @@ public class InstallController {
private FileAsyncCacheService fileAsyncCacheService;
@GetMapping("/is-installed")
@ResponseBody
public ResultBean isInstall() {
if (systemConfigService.getCurrentStorageStrategy() == null) {
return ResultBean.success();
@@ -51,7 +46,6 @@ public class InstallController {
@PostMapping("/install")
@ResponseBody
public ResultBean install(InstallModelDTO installModelDTO) throws Exception {
SystemConfigDTO systemConfigDTO = systemConfigService.getSystemConfig();
@@ -81,28 +75,13 @@ public class InstallController {
return ResultBean.success();
}
@PostMapping("/storage-strategy")
@ResponseBody
public ResultBean save(@RequestParam Map<String, String> storageStrategyConfig, StorageTypeEnum storageStrategy) throws Exception {
List<StorageConfig> storageConfigList = storageConfigService.selectStorageConfigByType(storageStrategy);
for (StorageConfig storageConfig : storageConfigList) {
String key = storageConfig.getKey();
String value = storageStrategyConfig.get(key);
storageConfig.setValue(value);
}
storageConfigService.updateStorageConfig(storageConfigList);
StorageTypeEnum currentStorageStrategy = systemConfigService.getCurrentStorageStrategy();
if (Objects.equals(storageStrategy, currentStorageStrategy)) {
AbstractFileService fileService = systemConfigService.getCurrentFileService();
fileService.clearCache();
if (systemConfigService.getEnableCache()) {
fileAsyncCacheService.cacheGlobalFile();
}
fileService.init();
}
return ResultBean.success();
@GetMapping("/form")
public ResultBean getFormByStorageType(String storageType) {
StorageTypeEnum storageTypeEnum = StorageTypeEnum.getEnum(storageType);
List<StorageConfig> storageConfigList = storageConfigService.selectStorageConfigByType(storageTypeEnum);
storageConfigList.forEach(storageConfig -> storageConfig.setValue(null));
return ResultBean.success(storageConfigList);
}
}
}

View File

@@ -13,4 +13,6 @@ public class CacheConfigDTO {
private boolean enableCache;
private boolean cacheFinish;
private Set<String> cacheKeys;
private Integer cacheDirectoryCount;
private Integer cacheFileCount;
}

View File

@@ -53,7 +53,7 @@ public enum StorageTypeEnum {
}
public static StorageTypeEnum getEnum(String value) {
return enumMap.get(value);
return enumMap.get(value.toLowerCase());
}
}

View File

@@ -12,6 +12,8 @@ import org.springframework.security.config.annotation.web.configuration.EnableWe
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.firewall.HttpFirewall;
import org.springframework.security.web.firewall.StrictHttpFirewall;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
@@ -98,6 +100,13 @@ public class MySecurityConfig extends WebSecurityConfigurerAdapter {
http.csrf().disable();
}
@Bean
public HttpFirewall allowUrlEncodedSlashHttpFirewall() {
StrictHttpFirewall firewall = new StrictHttpFirewall();
firewall.setAllowUrlEncodedPercent(true);
return firewall;
}
@Override
public void configure(AuthenticationManagerBuilder web) throws Exception {
web.userDetailsService(myUserDetailsServiceImpl()).passwordEncoder(passwordEncoder());
@@ -112,6 +121,7 @@ public class MySecurityConfig extends WebSecurityConfigurerAdapter {
public void configure(WebSecurity web) {
//对于在header里面增加token等类似情况放行所有OPTIONS请求。
web.ignoring().antMatchers(HttpMethod.OPTIONS, "/**");
web.httpFirewall(allowUrlEncodedSlashHttpFirewall());
}
@Bean

View File

@@ -29,7 +29,7 @@ import java.util.stream.Collectors;
* @date 2019/12/28 19:27
*/
@Slf4j
public abstract class AbstractFileService implements FileService {
public abstract class AbstractFileService extends FileCacheService implements FileService {
public static final String SYSTEM_CONFIG_CACHE_PREFIX = "zfile-cache:";
@@ -61,9 +61,9 @@ public abstract class AbstractFileService implements FileService {
public abstract List<FileItemDTO> fileList(String path) throws Exception;
/**
* 清理当前存储引擎的缓存
* 清理当前存储策略的缓存
*/
public void clearCache() throws Exception {
public void clearFileCache() throws Exception {
Set<String> cacheKeys = getCacheKeys();
cache.removeAll(cacheKeys);
closeCacheAutoRefresh();
@@ -96,8 +96,8 @@ public abstract class AbstractFileService implements FileService {
}
/**
* 获取存储引擎类型
* @return 存储引擎类型枚举
* 获取存储策略类型
* @return 存储策略类型枚举
*/
public abstract StorageTypeEnum getStorageTypeEnum();
@@ -187,7 +187,7 @@ public abstract class AbstractFileService implements FileService {
}
public void openCacheAutoRefresh() {
RefreshPolicy refreshPolicy = RefreshPolicy.newPolicy(1, TimeUnit.MINUTES);
RefreshPolicy refreshPolicy = RefreshPolicy.newPolicy(30, TimeUnit.MINUTES);
cache.config().setRefreshPolicy(refreshPolicy);
}

View File

@@ -21,6 +21,7 @@ import java.util.List;
* @date 2019/12/26 22:26
*/
public abstract class AbstractS3FileService extends AbstractFileService {
@Resource
protected StorageConfigService storageConfigService;

View File

@@ -1,5 +1,9 @@
package im.zhaojun.common.service;
import cn.hutool.core.util.ObjectUtil;
import com.alicp.jetcache.Cache;
import com.alicp.jetcache.anno.CacheType;
import com.alicp.jetcache.anno.CreateCache;
import im.zhaojun.common.config.StorageTypeFactory;
import im.zhaojun.common.model.dto.FileItemDTO;
import im.zhaojun.common.model.enums.FileTypeEnum;
@@ -20,6 +24,15 @@ import java.util.List;
@Service
public class FileAsyncCacheService {
public static final String CACHE_PROCESS_PREFIX = "zfile-process-cache:";
public static final String CACHE_FILE_COUNT_KEY = "file-count";
public static final String CACHE_DIRECTORY_COUNT_KEY = "directory-count";
@CreateCache(name = "SYSTEM_CONFIG_CACHE_PREFIX", cacheType = CacheType.LOCAL)
private Cache<String, Integer> cache;
private boolean cacheFinish;
@Resource
@@ -30,50 +43,95 @@ public class FileAsyncCacheService {
StorageTypeEnum storageStrategy = systemConfigService.getCurrentStorageStrategy();
if (storageStrategy == null) {
log.info("尚未配置存储策略. 跳过启动缓存.");
log.debug("尚未配置存储策略. 跳过启动缓存.");
return;
}
boolean enableCache = systemConfigService.getEnableCache();
if (!enableCache) {
log.info("未开启缓存, 跳过启动缓存");
log.debug("存储策略 {} 未启用缓存, 跳过缓存.", storageStrategy.getDescription());
return;
}
AbstractFileService fileService = StorageTypeFactory.getStorageTypeService(storageStrategy);
if (fileService.getIsUnInitialized()) {
log.info("存储引擎 {} 未初始化成功, 跳过启动缓存.", storageStrategy.getDescription());
log.debug("存储策略 {} 未初始化成功, 跳过缓存.", storageStrategy.getDescription());
return;
}
Integer cacheDirectoryCount = cache.get(CACHE_DIRECTORY_COUNT_KEY);
if (cacheDirectoryCount == null) {
cacheDirectoryCount = 0;
}
Integer cacheFileCount = cache.get(CACHE_FILE_COUNT_KEY);
if (cacheFileCount == null) {
cacheFileCount = 0;
}
log.info("缓存 {} 所有文件开始", storageStrategy.getDescription());
long startTime = System.currentTimeMillis();
try {
String path = "/";
FileService currentFileService = systemConfigService.getCurrentFileService();
List<FileItemDTO> fileItemList = currentFileService.fileList(path);
ArrayDeque<FileItemDTO> queue = new ArrayDeque<>(fileItemList);
List<FileItemDTO> rootFileItems = currentFileService.fileList("/");
ArrayDeque<FileItemDTO> queue = new ArrayDeque<>(rootFileItems);
while (!queue.isEmpty()) {
FileItemDTO fileItemDTO = queue.pop();
if (FileTypeEnum.FOLDER.equals(fileItemDTO.getType())) {
cacheDirectoryCount++;
}
if (FileTypeEnum.FILE.equals(fileItemDTO.getType())) {
cacheFileCount++;
}
log.debug("已缓存 {} 个文件夹", cacheDirectoryCount);
cache.put(CACHE_DIRECTORY_COUNT_KEY, cacheDirectoryCount);
log.debug("已缓存 {} 个文件", cacheFileCount);
cache.put(CACHE_FILE_COUNT_KEY, cacheFileCount);
if (fileItemDTO.getType() == FileTypeEnum.FOLDER) {
String filePath = StringUtils.removeDuplicateSeparator("/" + fileItemDTO.getPath() + "/" + fileItemDTO.getName() + "/");
queue.addAll(currentFileService.fileList(filePath));
List<FileItemDTO> fileItems = currentFileService.fileList(filePath);
queue.addAll(fileItems);
}
}
cache.put(CACHE_DIRECTORY_COUNT_KEY, cacheDirectoryCount);
cache.put(CACHE_FILE_COUNT_KEY, cacheFileCount);
} catch (Exception e) {
log.error("缓存所有文件失败", e);
e.printStackTrace();
}
long endTime = System.currentTimeMillis();
log.info("缓存 {} 所有文件结束, 用时: {} 秒", storageStrategy.getDescription(), ( (endTime - startTime) / 1000 ));
log.info("缓存 {} 所有文件结束, 用时: {} 秒, 文件夹共 {} 个, 文件共 {} 个",
storageStrategy.getDescription(),
( (endTime - startTime) / 1000 ), cacheDirectoryCount, cacheFileCount);
cacheFinish = true;
}
/**
* 清理缓存的文件/文件夹数量统计
*/
public void resetCacheCount() {
cache.remove(CACHE_DIRECTORY_COUNT_KEY);
cache.remove(CACHE_FILE_COUNT_KEY);
}
public Integer getCacheDirectoryCount() {
return ObjectUtil.defaultIfNull(cache.get(CACHE_DIRECTORY_COUNT_KEY), 0);
}
public Integer getCacheFileCount() {
return ObjectUtil.defaultIfNull(cache.get(CACHE_FILE_COUNT_KEY), 0);
}
public boolean isCacheFinish() {
return cacheFinish;
}

View File

@@ -0,0 +1,37 @@
package im.zhaojun.common.service;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
/**
* @author zhaojun
* @date 2020/1/11 14:08
*/
@Service
public class FileCacheService {
@Resource
private SystemConfigService systemConfigService;
@Resource
private FileAsyncCacheService fileAsyncCacheService;
public void enableCache() {
systemConfigService.updateCacheEnableConfig(true);
AbstractFileService currentFileService = systemConfigService.getCurrentFileService();
currentFileService.openCacheAutoRefresh();
fileAsyncCacheService.cacheGlobalFile();
}
public void disableCache() throws Exception {
systemConfigService.updateCacheEnableConfig(false);
AbstractFileService currentFileService = systemConfigService.getCurrentFileService();
currentFileService.clearFileCache();
fileAsyncCacheService.resetCacheCount();
}
}

View File

@@ -1,5 +1,7 @@
package im.zhaojun.common.service;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.crypto.SecureUtil;
import com.alicp.jetcache.Cache;
import com.alicp.jetcache.anno.CacheType;
@@ -10,11 +12,11 @@ import im.zhaojun.common.model.constant.SystemConfigConstant;
import im.zhaojun.common.model.dto.SystemConfigDTO;
import im.zhaojun.common.model.enums.StorageTypeEnum;
import im.zhaojun.common.repository.SystemConfigRepository;
import im.zhaojun.common.util.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
@@ -38,6 +40,11 @@ public class SystemConfigService {
@Resource
private FileAsyncCacheService fileAsyncCacheService;
@Resource
private FileCacheService fileCacheService;
private Class<SystemConfigDTO> systemConfigDTOClass = SystemConfigDTO.class;
public SystemConfigDTO getSystemConfig() {
Object cache = configCache.get(SYSTEM_CONFIG_CACHE_KEY);
if (configCache.get(SYSTEM_CONFIG_CACHE_KEY) != null) {
@@ -48,36 +55,20 @@ public class SystemConfigService {
List<SystemConfig> systemConfigList = systemConfigRepository.findAll();
for (SystemConfig systemConfig : systemConfigList) {
switch (systemConfig.getKey()) {
case SystemConfigConstant.SITE_NAME:
systemConfigDTO.setSiteName(systemConfig.getValue());
break;
case SystemConfigConstant.INFO_ENABLE:
systemConfigDTO.setInfoEnable("true".equals(systemConfig.getValue()));
break;
case SystemConfigConstant.SEARCH_ENABLE:
systemConfigDTO.setSearchEnable("true".equals(systemConfig.getValue()));
break;
case SystemConfigConstant.SEARCH_IGNORE_CASE:
systemConfigDTO.setSearchIgnoreCase("true".equals(systemConfig.getValue()));
break;
case SystemConfigConstant.STORAGE_STRATEGY:
String value = systemConfig.getValue();
systemConfigDTO.setStorageStrategy(StorageTypeEnum.getEnum(value));
break;
case SystemConfigConstant.USERNAME:
systemConfigDTO.setUsername(systemConfig.getValue());
break;
case SystemConfigConstant.PASSWORD:
systemConfigDTO.setPassword(systemConfig.getValue());
break;
case SystemConfigConstant.DOMAIN:
systemConfigDTO.setDomain(systemConfig.getValue());
break;
case SystemConfigConstant.ENABLE_CACHE:
systemConfigDTO.setEnableCache("true".equals(systemConfig.getValue()));
break;
default:break;
String key = systemConfig.getKey();
try {
Field field = systemConfigDTOClass.getDeclaredField(key);
if (field != null) {
field.setAccessible(true);
String strVal = systemConfig.getValue();
Object convertVal = Convert.convert(field.getType(), strVal);
field.set(systemConfigDTO, convertVal);
}
} catch (NoSuchFieldException | IllegalAccessException e) {
if (log.isDebugEnabled()) {
log.debug("通过反射, 将字段 {" + key + "}注入 SystemConfigDTO 时出现异常:", e);
}
}
}
@@ -85,52 +76,26 @@ public class SystemConfigService {
return systemConfigDTO;
}
public void updateSystemConfig(SystemConfigDTO systemConfigDTO) throws Exception {
public void updateSystemConfig(SystemConfigDTO systemConfigDTO) throws Exception {
List<SystemConfig> systemConfigList = new ArrayList<>();
SystemConfig systemConfig = systemConfigRepository.findByKey(SystemConfigConstant.SITE_NAME);
systemConfig.setValue(systemConfigDTO.getSiteName());
systemConfigList.add(systemConfig);
SystemConfig domainConfig = systemConfigRepository.findByKey(SystemConfigConstant.DOMAIN);
domainConfig.setValue(systemConfigDTO.getDomain());
systemConfigList.add(domainConfig);
SystemConfig infoEnableSystemConfig = systemConfigRepository.findByKey(SystemConfigConstant.INFO_ENABLE);
infoEnableSystemConfig.setValue(systemConfigDTO.getInfoEnable() ? "true" : "false");
systemConfigList.add(infoEnableSystemConfig);
SystemConfig searchEnableSystemConfig = systemConfigRepository.findByKey(SystemConfigConstant.SEARCH_ENABLE);
searchEnableSystemConfig.setValue(systemConfigDTO.getSearchEnable() ? "true" : "false");
systemConfigList.add(searchEnableSystemConfig);
SystemConfig searchIgnoreCaseSystemConfig = systemConfigRepository.findByKey(SystemConfigConstant.SEARCH_IGNORE_CASE);
searchIgnoreCaseSystemConfig.setValue(systemConfigDTO.getSearchIgnoreCase() ? "true" : "false");
systemConfigList.add(searchIgnoreCaseSystemConfig);
Field[] fields = systemConfigDTOClass.getDeclaredFields();
for (Field field : fields) {
String key = field.getName();
SystemConfig systemConfig = systemConfigRepository.findByKey(key);
if (systemConfig != null) {
field.setAccessible(true);
Object val = field.get(systemConfigDTO);
if (val != null) {
systemConfig.setValue(val.toString());
systemConfigList.add(systemConfig);
}
}
}
boolean oldEnableCache = getEnableCache();
Boolean curEnableCache = systemConfigDTO.getEnableCache();
SystemConfig enableCacheSystemConfig = systemConfigRepository.findByKey(SystemConfigConstant.ENABLE_CACHE);
enableCacheSystemConfig.setValue(systemConfigDTO.getEnableCache() ? "true" : "false");
systemConfigList.add(enableCacheSystemConfig);
SystemConfig storageStrategySystemConfig = systemConfigRepository.findByKey(SystemConfigConstant.STORAGE_STRATEGY);
storageStrategySystemConfig.setValue(systemConfigDTO.getStorageStrategy().getKey());
systemConfigList.add(storageStrategySystemConfig);
if (StringUtils.isNotNullOrEmpty(systemConfigDTO.getUsername())) {
SystemConfig usernameSystemConfig = systemConfigRepository.findByKey(SystemConfigConstant.USERNAME);
usernameSystemConfig.setValue(systemConfigDTO.getUsername());
systemConfigList.add(usernameSystemConfig);
}
if (StringUtils.isNotNullOrEmpty(systemConfigDTO.getPassword())) {
SystemConfig passwordSystemConfig = systemConfigRepository.findByKey(SystemConfigConstant.PASSWORD);
passwordSystemConfig.setValue(systemConfigDTO.getPassword());
systemConfigList.add(passwordSystemConfig);
}
boolean curEnableCache = ObjectUtil.defaultIfNull(systemConfigDTO.getEnableCache(), false);
configCache.remove(SYSTEM_CONFIG_CACHE_KEY);
@@ -140,16 +105,16 @@ public class SystemConfigService {
if (!oldEnableCache && curEnableCache) {
log.debug("检测到开启了缓存, 开启预热缓存");
currentFileService.openCacheAutoRefresh();
fileAsyncCacheService.cacheGlobalFile();
fileCacheService.enableCache();
}
if (oldEnableCache && !curEnableCache) {
log.debug("检测到关闭了缓存, 正在清理缓存数据及关闭自动刷新");
currentFileService.clearCache();
fileCacheService.disableCache();
}
}
public void updateUsernameAndPwd(String username, String password) {
SystemConfig usernameConfig = systemConfigRepository.findByKey(SystemConfigConstant.USERNAME);
usernameConfig.setValue(username);
@@ -164,19 +129,30 @@ public class SystemConfigService {
systemConfigRepository.save(systemConfig);
}
public void updateCacheEnableConfig(Boolean isEnable) {
SystemConfig enableConfig = systemConfigRepository.findByKey(SystemConfigConstant.ENABLE_CACHE);
enableConfig.setValue(isEnable.toString());
systemConfigRepository.save(enableConfig);
configCache.remove(SYSTEM_CONFIG_CACHE_KEY);
}
public AbstractFileService getCurrentFileService() {
StorageTypeEnum storageStrategy = getCurrentStorageStrategy();
return StorageTypeFactory.getStorageTypeService(storageStrategy);
}
public StorageTypeEnum getCurrentStorageStrategy() {
SystemConfigDTO systemConfigDTO = getSystemConfig();
return systemConfigDTO.getStorageStrategy();
}
public boolean getEnableCache() {
SystemConfigDTO systemConfigDTO = getSystemConfig();
return systemConfigDTO.getEnableCache();
return ObjectUtil.defaultIfNull(systemConfigDTO.getEnableCache(), false);
}
}

View File

@@ -48,7 +48,7 @@ public class AudioHelper {
AudioInfoDTO audioInfoDTO = new AudioInfoDTO();
audioInfoDTO.setTitle("未知歌曲");
audioInfoDTO.setArtist("未知");
audioInfoDTO.setCover("/shikwasa/audio.png");
audioInfoDTO.setCover("http://c.jun6.net/audio.png");
Mp3File mp3File = null;
try {

View File

@@ -1,11 +1,13 @@
package im.zhaojun.common.util;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;
/**
* @author zhaojun
*/
@Slf4j
public class HttpUtil {
public static String getTextContent(String url) {
@@ -19,8 +21,7 @@ public class HttpUtil {
try {
restTemplate.headForHeaders(url);
return true;
} catch (RestClientException e) {
e.printStackTrace();
} catch (RestClientException ignored) {
}
return false;
}

View File

@@ -37,6 +37,7 @@ public class HuaweiServiceImpl extends AbstractS3FileService implements FileServ
basePath = stringStorageConfigMap.get(StorageConfigConstant.BASE_PATH).getValue();
if (Objects.isNull(accessKey) || Objects.isNull(secretKey) || Objects.isNull(endPoint) || Objects.isNull(bucketName)) {
log.debug("初始化存储策略 [{}] 失败: 参数不完整", getStorageTypeEnum().getDescription());
isInitialized = false;
} else {
BasicAWSCredentials credentials = new BasicAWSCredentials(accessKey, secretKey);

View File

@@ -32,7 +32,7 @@ public class LocalController {
public ResponseEntity<FileSystemResource> downAttachment(final HttpServletRequest request) {
String path = (String) request.getAttribute(
HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE);
String bestMatchPattern = (String ) request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE);
String bestMatchPattern = (String) request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE);
AntPathMatcher apm = new AntPathMatcher();
String filePath = apm.extractPathWithinPattern(bestMatchPattern, path);
@@ -41,6 +41,11 @@ public class LocalController {
private ResponseEntity<FileSystemResource> export(File file) {
if (!file.exists()) {
return ResponseEntity.notFound().build();
}
MediaType mediaType = MediaType.APPLICATION_OCTET_STREAM;
HttpHeaders headers = new HttpHeaders();

View File

@@ -1,5 +1,6 @@
package im.zhaojun.local.service;
import cn.hutool.core.util.URLUtil;
import im.zhaojun.common.model.StorageConfig;
import im.zhaojun.common.model.SystemConfig;
import im.zhaojun.common.model.constant.StorageConfigConstant;
@@ -47,6 +48,7 @@ public class LocalServiceImpl extends AbstractFileService implements FileService
storageConfigService.selectStorageConfigMapByKey(StorageTypeEnum.LOCAL);
filePath = stringStorageConfigMap.get(StorageConfigConstant.FILE_PATH_KEY).getValue();
if (Objects.isNull(filePath)) {
log.debug("初始化存储策略 [{}] 失败: 参数不完整", getStorageTypeEnum().getDescription());
isInitialized = false;
} else {
isInitialized = testConnection();
@@ -87,7 +89,7 @@ public class LocalServiceImpl extends AbstractFileService implements FileService
@Override
public String getDownloadUrl(String path) {
SystemConfig usernameConfig = systemConfigRepository.findByKey(SystemConfigConstant.DOMAIN);
return StringUtils.removeDuplicateSeparator(usernameConfig.getValue() + "/file/" + path);
return URLUtil.encode(StringUtils.removeDuplicateSeparator(usernameConfig.getValue() + "/file/" + path));
}
public String getFilePath() {

View File

@@ -35,6 +35,7 @@ public class MinIOServiceImpl extends AbstractS3FileService implements FileServi
basePath = stringStorageConfigMap.get(StorageConfigConstant.BASE_PATH).getValue();
if (Objects.isNull(accessKey) || Objects.isNull(secretKey) || Objects.isNull(endPoint) || Objects.isNull(bucketName)) {
log.debug("初始化存储策略 [{}] 失败: 参数不完整", getStorageTypeEnum().getDescription());
isInitialized = false;
} else {
BasicAWSCredentials credentials = new BasicAWSCredentials(accessKey, secretKey);

View File

@@ -37,6 +37,7 @@ public class QiniuServiceImpl extends AbstractS3FileService implements FileServi
basePath = stringStorageConfigMap.get(StorageConfigConstant.BASE_PATH).getValue();
if (Objects.isNull(accessKey) || Objects.isNull(secretKey) || Objects.isNull(endPoint) || Objects.isNull(bucketName)) {
log.debug("初始化存储策略 [{}] 失败: 参数不完整", getStorageTypeEnum().getDescription());
isInitialized = false;
} else {
BasicAWSCredentials credentials = new BasicAWSCredentials(accessKey, secretKey);

View File

@@ -36,6 +36,7 @@ public class TencentServiceImpl extends AbstractS3FileService implements FileSer
basePath = stringStorageConfigMap.get(StorageConfigConstant.BASE_PATH).getValue();
if (Objects.isNull(secretId) || Objects.isNull(secretKey) || Objects.isNull(endPoint) || Objects.isNull(bucketName)) {
log.debug("初始化存储策略 [{}] 失败: 参数不完整", getStorageTypeEnum().getDescription());
isInitialized = false;
} else {
BasicAWSCredentials credentials = new BasicAWSCredentials(secretId, secretKey);

View File

@@ -55,6 +55,7 @@ public class UpYunServiceImpl extends AbstractFileService implements FileService
basePath = ObjectUtil.defaultIfNull(basePath, "");
if (Objects.isNull(bucketName) || Objects.isNull(username) || Objects.isNull(password)) {
log.debug("初始化存储策略 [{}] 失败: 参数不完整", getStorageTypeEnum().getDescription());
isInitialized = false;
} else {
upYun = new UpYun(bucketName, username, password);

View File

@@ -1,9 +1,3 @@
logging:
level:
im:
zhaojun: info
path: ${user.home}/.zfile/logs
server:
port: 8080
servlet:
@@ -40,10 +34,12 @@ spring:
properties:
hibernate:
format_sql: false
show-sql: true
show-sql: false
resources:
chain:
gzipped: true
profiles:
active: prod
zfile:
cache:
timeout: 300
@@ -58,5 +54,4 @@ jetcache:
local:
default:
type: caffeine
keyConvertor: fastjson
defaultExpireInMillis: 3600000
keyConvertor: fastjson

View File

@@ -0,0 +1,88 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
scan当此属性设置为true时配置文件如果发生改变将会被重新加载默认值为true。
scanPeriod设置监测配置文件是否有修改的时间间隔如果没有给出时间单位默认单位是毫秒当scan为true时此属性生效。默认的时间间隔为1分钟。
debug当此属性设置为true时将打印出logback内部日志信息实时查看logback运行状态。默认值为false。
-->
<configuration scan="false" scanPeriod="60 seconds" debug="false">
<conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter" />
<conversionRule conversionWord="wex" converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter" />
<conversionRule conversionWord="wEx" converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter"/>
<!-- 定义日志的根目录 -->
<property name="LOG_HOME" value="${user.home}/.zfile/logs" />
<!-- 定义日志文件名称 -->
<property name="appName" value="zfile"/>
<!-- ch.qos.logback.core.ConsoleAppender 表示控制台输出 -->
<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>INFO</level>
</filter>
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>%clr(%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}</pattern>
</layout>
</appender>
<!-- 滚动记录文件,先将日志记录到指定文件,当符合某个条件时,将日志记录到其他文件 -->
<appender name="appLogAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 指定日志文件的名称 -->
<file>${LOG_HOME}/${appName}.log</file>
<!--
当发生滚动时,决定 RollingFileAppender 的行为,涉及文件移动和重命名
TimeBasedRollingPolicy 最常用的滚动策略,它根据时间来制定滚动策略,既负责滚动也负责出发滚动。
-->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--
滚动时产生的文件的存放位置及文件名称 %d{yyyy-MM-dd}:按天进行日志滚动
%i当文件大小超过maxFileSize时按照i进行文件滚动
-->
<fileNamePattern>${LOG_HOME}/${appName}-%d{yyyy-MM-dd}-%i.log</fileNamePattern>
<!--
可选节点,控制保留的归档文件的最大数量,超出数量就删除旧文件。假设设置每天滚动,
且maxHistory是365则只保存最近365天的文件删除之前的旧文件。注意删除旧文件是
那些为了归档而创建的目录也会被删除。
-->
<MaxHistory>365</MaxHistory>
<!--
当日志文件超过maxFileSize指定的大小是根据上面提到的%i进行日志文件滚动 注意此处配置SizeBasedTriggeringPolicy是无法实现按文件大小进行滚动的必须配置timeBasedFileNamingAndTriggeringPolicy
-->
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>5MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<!-- 日志输出格式: -->
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}} ${LOG_LEVEL_PATTERN:-%5p} ${PID:- } --- [%t] %-40.40logger{39} : %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}</pattern>
</layout>
</appender>
<!--
logger主要用于存放日志对象也可以定义日志类型、级别
name表示匹配的logger类型前缀也就是包的前半部分
level要记录的日志级别包括 TRACE < DEBUG < INFO < WARN < ERROR
additivity作用在于children-logger是否使用 rootLogger配置的appender进行输出
false表示只用当前logger的appender-reftrue
表示当前logger的appender-ref和rootLogger的appender-ref都有效
-->
<!-- jetCache logger -->
<logger name="com.alicp" level="debug"/>
<!-- hibernate logger -->
<logger name="org.hibernate.SQL" level="DEBUG"/>
<!--
root与logger是父子关系没有特别定义则默认为root任何一个类只会和一个logger对应
要么是定义的logger要么是root判断的关键在于找到这个logger然后判断这个logger的appender和level。
-->
<root level="info">
<appender-ref ref="stdout" />
<appender-ref ref="appLogAppender" />
</root>
</configuration>

View File

@@ -0,0 +1 @@
.el-menu[data-v-0d38e212],.el-row[data-v-0d38e212]{height:100vh}

View File

@@ -1 +0,0 @@
.el-menu[data-v-4fea46ab],.el-row[data-v-4fea46ab]{height:100vh}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
.box-card[data-v-621306e1]{padding-top:30px;padding-right:30px;margin:15vh auto;height:65vh;overflow-y:auto}.el-select[data-v-621306e1]{width:100%}

View File

@@ -0,0 +1 @@
.box-card[data-v-23a15e8c]{padding-top:30px;padding-right:30px;margin:15vh auto;height:65vh;overflow-y:auto}.el-select[data-v-23a15e8c]{width:100%}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 10 KiB

View File

@@ -1 +1 @@
<!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1"><link rel=icon href=/favicon.ico><title></title><link href=/css/adminIndex.67225c93.css rel=prefetch><link href=/css/install.39da241e.css rel=prefetch><link href=/js/adminIndex.57637329.js rel=prefetch><link href=/js/dplayer.acc587f7.js rel=prefetch><link href=/js/install.3ac7201f.js rel=prefetch><link href=/css/app.46f70347.css rel=preload as=style><link href=/css/chunk-vendors.b9a3d604.css rel=preload as=style><link href=/js/app.362c49b5.js rel=preload as=script><link href=/js/chunk-vendors.10f10391.js rel=preload as=script><link href=/css/chunk-vendors.b9a3d604.css rel=stylesheet><link href=/css/app.46f70347.css rel=stylesheet></head><body><noscript><strong>We're sorry but zfile doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id=app></div><script src=/js/chunk-vendors.10f10391.js></script><script src=/js/app.362c49b5.js></script></body></html>
<!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1"><link rel=icon href=/favicon.ico><title></title><link href=/css/adminIndex.25eab1c6.css rel=prefetch><link href=/css/install.ca398206.css rel=prefetch><link href=/js/adminIndex.456ac23a.js rel=prefetch><link href=/js/dplayer.acc587f7.js rel=prefetch><link href=/js/install.7e582096.js rel=prefetch><link href=/css/app.9a6cb5c2.css rel=preload as=style><link href=/css/chunk-vendors.b9a3d604.css rel=preload as=style><link href=/js/app.022a9bb1.js rel=preload as=script><link href=/js/chunk-vendors.3fc3f2af.js rel=preload as=script><link href=/css/chunk-vendors.b9a3d604.css rel=stylesheet><link href=/css/app.9a6cb5c2.css rel=stylesheet></head><body><noscript><strong>We're sorry but zfile doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id=app></div><script src=/js/chunk-vendors.3fc3f2af.js></script><script src=/js/app.022a9bb1.js></script></body></html>

View File

@@ -0,0 +1 @@
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["adminIndex"],{7869:function(t,e,a){},adf4:function(t,e,a){"use strict";a.r(e);var i=function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("el-row",[a("el-col",{attrs:{span:3}},[a("el-menu",{staticClass:"el-menu-vertical-demo",attrs:{"default-active":"/admin"!==this.$route.path?this.$route.path:"/admin/site",router:!0}},[a("el-menu-item",{attrs:{index:"/admin/site"}},[a("i",{staticClass:"el-icon-setting"}),a("span",{attrs:{slot:"title"},slot:"title"},[t._v("站点设置")])]),a("el-menu-item",{attrs:{index:"/admin/storage"}},[a("i",{staticClass:"el-icon-s-operation"}),a("span",{attrs:{slot:"title"},slot:"title"},[t._v("存储策略")])]),a("el-menu-item",{attrs:{index:"/admin/password"}},[a("i",{staticClass:"el-icon-key"}),a("span",{attrs:{slot:"title"},slot:"title"},[t._v("修改密码")])]),a("el-menu-item",{attrs:{index:"/admin/cache"}},[a("i",{staticClass:"el-icon-collection"}),a("span",{attrs:{slot:"title"},slot:"title"},[t._v("缓存管理")])])],1)],1),a("el-col",{attrs:{span:16}},[a("keep-alive",{attrs:{exclude:"CacheManager,SiteSetting"}},[a("router-view")],1)],1)],1)},s=[],n={name:"Index",data:function(){return{active:"/admin/storage"}}},l=n,o=(a("f2cb"),a("2877")),r=Object(o["a"])(l,i,s,!1,null,"0d38e212",null);e["default"]=r.exports},f2cb:function(t,e,a){"use strict";var i=a("7869"),s=a.n(i);s.a}}]);

View File

@@ -1 +0,0 @@
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["adminIndex"],{"7bf3":function(t,e,a){"use strict";var s=a("ed6d"),i=a.n(s);i.a},adf4:function(t,e,a){"use strict";a.r(e);var s=function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("el-row",[a("el-col",{attrs:{span:3}},[a("el-menu",{staticClass:"el-menu-vertical-demo",attrs:{"default-active":"/admin"!==this.$route.path?this.$route.path:"/admin/site",router:!0}},[a("el-menu-item",{attrs:{index:"/admin/site"}},[a("i",{staticClass:"el-icon-setting"}),a("span",{attrs:{slot:"title"},slot:"title"},[t._v("站点设置")])]),a("el-menu-item",{attrs:{index:"/admin/storage"}},[a("i",{staticClass:"el-icon-s-operation"}),a("span",{attrs:{slot:"title"},slot:"title"},[t._v("存储策略")])]),a("el-menu-item",{attrs:{index:"/admin/password"}},[a("i",{staticClass:"el-icon-key"}),a("span",{attrs:{slot:"title"},slot:"title"},[t._v("修改密码")])]),a("el-menu-item",{attrs:{index:"/admin/cache"}},[a("i",{staticClass:"el-icon-collection"}),a("span",{attrs:{slot:"title"},slot:"title"},[t._v("缓存管理")])])],1)],1),a("el-col",{attrs:{span:12}},[a("keep-alive",{attrs:{exclude:"CacheManager"}},[a("router-view")],1)],1)],1)},i=[],n={name:"Index",data:function(){return{active:"/admin/storage"}}},l=n,o=(a("7bf3"),a("2877")),r=Object(o["a"])(l,s,i,!1,null,"4fea46ab",null);e["default"]=r.exports},ed6d:function(t,e,a){}}]);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["install"],{4904:function(e,t,a){"use strict";var r=a("dfa0"),o=a.n(r);o.a},dfa0:function(e,t,a){},f8a7:function(e,t,a){"use strict";a.r(t);var r=function(){var e=this,t=e.$createElement,a=e._self._c||t;return a("el-row",{attrs:{gutter:20}},[a("el-col",{attrs:{span:8,offset:8}},[a("el-card",{staticClass:"box-card",attrs:{"align-center":"",shadow:"always"}},[a("el-form",{ref:"form",attrs:{rules:e.rules,model:e.form,"label-width":"auto","status-icon":!0}},[a("el-form-item",{attrs:{label:"站点名称",prop:"siteName"}},[a("el-input",{model:{value:e.form.siteName,callback:function(t){e.$set(e.form,"siteName",t)},expression:"form.siteName"}})],1),a("el-form-item",{attrs:{label:"管理员账号",prop:"username"}},[a("el-input",{model:{value:e.form.username,callback:function(t){e.$set(e.form,"username","string"===typeof t?t.trim():t)},expression:"form.username"}})],1),a("el-form-item",{attrs:{label:"管理员密码",prop:"password"}},[a("el-input",{model:{value:e.form.password,callback:function(t){e.$set(e.form,"password","string"===typeof t?t.trim():t)},expression:"form.password"}})],1),a("el-form-item",{attrs:{label:"站点地址/域名",prop:"domain"}},[a("el-input",{model:{value:e.form.domain,callback:function(t){e.$set(e.form,"domain","string"===typeof t?t.trim():t)},expression:"form.domain"}})],1),a("el-form-item",{attrs:{label:"存储策略"}},[a("el-select",{attrs:{placeholder:"请选择存储策略"},model:{value:e.form.storageStrategy,callback:function(t){e.$set(e.form,"storageStrategy",t)},expression:"form.storageStrategy"}},[a("el-option",{attrs:{label:"阿里云 OSS",value:"aliyun"}}),a("el-option",{attrs:{label:"腾讯云 COS",value:"tencent"}}),a("el-option",{attrs:{label:"华为云 OBS",value:"huawei"}}),a("el-option",{attrs:{label:"七牛云 KODO",value:"qiniu"}}),a("el-option",{attrs:{label:"又拍云 USS",value:"upyun"}}),a("el-option",{attrs:{label:"FTP",value:"ftp"}}),a("el-option",{attrs:{label:"本地存储",value:"local"}}),a("el-option",{attrs:{label:"minio",value:"minio"}})],1)],1),e._l(e.storageStrategyForm,(function(t){return a("el-form-item",{key:t.title,attrs:{label:t.title}},["endPoint"===t.key&&e.region.hasOwnProperty(e.form.storageStrategy)?a("el-select",{model:{value:e.form.storageStrategyConfig.endPoint,callback:function(t){e.$set(e.form.storageStrategyConfig,"endPoint",t)},expression:"form.storageStrategyConfig.endPoint"}},e._l(e.region[e.form.storageStrategy],(function(e){return a("el-option",{key:e.name,attrs:{label:e.name,value:e.val}})})),1):a("el-input",{model:{value:e.form.storageStrategyConfig[t.key],callback:function(a){e.$set(e.form.storageStrategyConfig,t.key,"string"===typeof a?a.trim():a)},expression:"form.storageStrategyConfig[item.key]"}})],1)})),a("el-form-item",[a("el-button",{attrs:{type:"primary"},on:{click:function(t){return e.submitForm("form")}}},[e._v("确认")])],1)],2)],1)],1)],1)},o=[],n=a("4328"),s=a.n(n),i=a("245d"),l={name:"Install",data:function(){return{active:1,form:{siteName:"",storageStrategy:"",username:"",password:"",domain:window.location.protocol+"//"+window.location.host,storageStrategyConfig:{endPoint:""}},storageStrategyForm:[],region:i["a"],rules:{siteName:[{required:!0,message:"请输入站点名称",trigger:"change"}],username:[{required:!0,message:"请输入管理员账号",trigger:"change"}],password:[{required:!0,message:"请输入管理员密码",trigger:"change"}],domain:[{required:!0,type:"url",message:"请输入正确的域名, 需以 http:// 或 https:// 开头",trigger:"change"}]}}},watch:{"form.storageStrategy":function(e){var t=this;this.$http.get("api/form",{params:{storageType:e}}).then((function(e){t.form.storageStrategyConfig.endPoint=null,t.storageStrategyForm=e.data.data}))}},methods:{submitForm:function(e){var t=this;this.$refs[e].validate((function(e){if(!e)return!1;var a=t;t.$http.post("install",s.a.stringify(t.form)).then((function(e){var r=e.data;t.$message({message:r.msg,type:0===r.code?"success":"error",duration:1500,onClose:function(){a.$router.push("/main")}})}))}))}},created:function(){var e=this;this.$http.get("is-installed").then((function(t){var a=t.data;0!==a.code&&e.$router.push("/main")}))}},m=l,u=(a("4904"),a("2877")),f=Object(u["a"])(m,r,o,!1,null,"621306e1",null);t["default"]=f.exports}}]);

View File

@@ -0,0 +1 @@
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["install"],{"45a3":function(e,t,a){},6796:function(e,t,a){"use strict";var r=a("45a3"),o=a.n(r);o.a},f8a7:function(e,t,a){"use strict";a.r(t);var r=function(){var e=this,t=e.$createElement,a=e._self._c||t;return a("el-row",{attrs:{gutter:20}},[a("el-col",{attrs:{span:8,offset:8}},[a("el-card",{staticClass:"box-card",attrs:{"align-center":"",shadow:"always"}},[a("el-form",{ref:"form",attrs:{rules:e.rules,model:e.form,"label-width":"auto","status-icon":!0}},[a("el-form-item",{attrs:{label:"站点名称",prop:"siteName"}},[a("el-input",{model:{value:e.form.siteName,callback:function(t){e.$set(e.form,"siteName",t)},expression:"form.siteName"}})],1),a("el-form-item",{attrs:{label:"管理员账号",prop:"username"}},[a("el-input",{model:{value:e.form.username,callback:function(t){e.$set(e.form,"username","string"===typeof t?t.trim():t)},expression:"form.username"}})],1),a("el-form-item",{attrs:{label:"管理员密码",prop:"password"}},[a("el-input",{model:{value:e.form.password,callback:function(t){e.$set(e.form,"password","string"===typeof t?t.trim():t)},expression:"form.password"}})],1),a("el-form-item",{attrs:{label:"站点地址/域名",prop:"domain"}},[a("el-input",{model:{value:e.form.domain,callback:function(t){e.$set(e.form,"domain","string"===typeof t?t.trim():t)},expression:"form.domain"}})],1),a("el-form-item",{attrs:{label:"存储策略"}},[a("el-select",{attrs:{placeholder:"请选择存储策略"},model:{value:e.form.storageStrategy,callback:function(t){e.$set(e.form,"storageStrategy",t)},expression:"form.storageStrategy"}},[a("el-option",{attrs:{label:"阿里云 OSS",value:"aliyun"}}),a("el-option",{attrs:{label:"腾讯云 COS",value:"tencent"}}),a("el-option",{attrs:{label:"华为云 OBS",value:"huawei"}}),a("el-option",{attrs:{label:"七牛云 KODO",value:"qiniu"}}),a("el-option",{attrs:{label:"又拍云 USS",value:"upyun"}}),a("el-option",{attrs:{label:"FTP",value:"ftp"}}),a("el-option",{attrs:{label:"本地存储",value:"local"}}),a("el-option",{attrs:{label:"minio",value:"minio"}})],1)],1),e._l(e.storageStrategyForm,(function(t){return a("el-form-item",{key:t.title,attrs:{label:t.title}},["endPoint"===t.key&&e.region.hasOwnProperty(e.form.storageStrategy)?a("el-select",{model:{value:e.form.storageStrategyConfig.endPoint,callback:function(t){e.$set(e.form.storageStrategyConfig,"endPoint",t)},expression:"form.storageStrategyConfig.endPoint"}},e._l(e.region[e.form.storageStrategy],(function(e){return a("el-option",{key:e.name,attrs:{label:e.name,value:e.val}})})),1):a("el-input",{model:{value:e.form.storageStrategyConfig[t.key],callback:function(a){e.$set(e.form.storageStrategyConfig,t.key,"string"===typeof a?a.trim():a)},expression:"form.storageStrategyConfig[item.key]"}})],1)})),a("el-form-item",[a("el-button",{attrs:{type:"primary"},on:{click:function(t){return e.submitForm("form")}}},[e._v("确认")])],1)],2)],1)],1)],1)},o=[],n=a("4328"),s=a.n(n),i=a("245d"),l={name:"Install",data:function(){return{active:1,form:{siteName:"",storageStrategy:"",username:"",password:"",domain:window.location.protocol+"//"+window.location.host,storageStrategyConfig:{endPoint:""}},storageStrategyForm:[],region:i["a"],rules:{siteName:[{required:!0,message:"请输入站点名称",trigger:"change"}],username:[{required:!0,message:"请输入管理员账号",trigger:"change"}],password:[{required:!0,message:"请输入管理员密码",trigger:"change"}],domain:[{required:!0,type:"url",message:"请输入正确的域名, 需以 http:// 或 https:// 开头",trigger:"change"}]}}},watch:{"form.storageStrategy":function(e){var t=this;this.$http.get("form",{params:{storageType:e}}).then((function(e){t.form.storageStrategyConfig.endPoint=null,t.storageStrategyForm=e.data.data}))}},methods:{submitForm:function(e){var t=this;this.$refs[e].validate((function(e){if(!e)return!1;var a=t;t.$http.post("install",s.a.stringify(t.form)).then((function(e){var r=e.data;t.$message({message:r.msg,type:0===r.code?"success":"error",duration:1500,onClose:function(){a.$router.push("/main")}})}))}))}},created:function(){var e=this;this.$http.get("is-installed").then((function(t){var a=t.data;0!==a.code&&e.$router.push("/main")}))}},m=l,u=(a("6796"),a("2877")),f=Object(u["a"])(m,r,o,!1,null,"23a15e8c",null);t["default"]=f.exports}}]);