mirror of
https://github.com/zfile-dev/zfile.git
synced 2025-04-19 05:34:52 +00:00
Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7e8cab90d0 | ||
|
|
4d5743dc0b | ||
|
|
1a326cc17d | ||
|
|
cc993d8e65 | ||
|
|
f128882034 | ||
|
|
31dbb902c3 | ||
|
|
c849057aaa | ||
|
|
7b288b795c | ||
|
|
316566d479 | ||
|
|
e01ce28eb8 | ||
|
|
9b7528b61c | ||
|
|
bd22cfd34c | ||
|
|
4aa9839c6b | ||
|
|
5eeea23703 | ||
|
|
6997b15dd0 | ||
|
|
326c954c36 |
14
README.md
14
README.md
@@ -9,7 +9,7 @@
|
||||
|
||||
前端基于 [h5ai](https://larsjung.de/h5ai/) 的原有功能使用 Vue 重新开发了一遍. 后端采用 SpringBoot, 数据库采用内嵌数据库.
|
||||
|
||||
预览地址: [http://zfile.jun6.net](http://zfile.jun6.net)
|
||||
预览地址: [https://zfile.jun6.net](https://zfile.jun6.net)
|
||||
|
||||
## 系统特色
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
* 个性化配置
|
||||
* 自定义目录的 header 和 footer 说明文件
|
||||
* 文件夹密码
|
||||
* 支持在线浏览文本文件, 视频, 图片, 音乐.
|
||||
* 支持在线浏览文本文件, 视频, 图片, 音乐. (支持 FLV 和 HLS)
|
||||
* 文件/目录二维码
|
||||
* 缓存动态开启, 缓存自动刷新
|
||||
* 全局搜索
|
||||
@@ -28,25 +28,25 @@
|
||||
安装 JDK 1.8 :
|
||||
|
||||
```bash
|
||||
yum instal -y java # 适用于 Centos 7.x
|
||||
yum install -y java # 适用于 Centos 7.x
|
||||
```
|
||||
|
||||
下载项目:
|
||||
|
||||
```bash
|
||||
wget https://github.com/zhaojun1998/zfile/releases/download/0.3.1/zfile-0.3.1.jar
|
||||
wget https://github.com/zhaojun1998/zfile/releases/download/0.5/zfile-0.5.jar
|
||||
```
|
||||
|
||||
启动项目:
|
||||
|
||||
```bash
|
||||
java -Djava.security.egd=file:/dev/./urandom -jar zfile-0.3.1.jar
|
||||
java -Djava.security.egd=file:/dev/./urandom -jar zfile-0.5.jar
|
||||
|
||||
## 高级启动
|
||||
java -Djava.security.egd=file:/dev/./urandom -jar zfile-0.3.1.jar --server.port=18777
|
||||
java -Djava.security.egd=file:/dev/./urandom -jar zfile-0.5.jar --server.port=18777
|
||||
|
||||
## 后台运行
|
||||
nohup java -Djava.security.egd=file:/dev/./urandom -jar zfile-0.3.1.jar &
|
||||
nohup java -Djava.security.egd=file:/dev/./urandom -jar zfile-0.5.jar &
|
||||
```
|
||||
|
||||
> 系统使用的是内置配置文件, 默认配置请参考: [application.yml](https://github.com/zhaojun1998/zfile/blob/master/src/main/resources/application.yml)
|
||||
|
||||
2
pom.xml
2
pom.xml
@@ -12,7 +12,7 @@
|
||||
|
||||
<groupId>im.zhaojun</groupId>
|
||||
<artifactId>zfile</artifactId>
|
||||
<version>0.3.1</version>
|
||||
<version>0.5</version>
|
||||
<name>zfile</name>
|
||||
<description>一个在线的文件浏览系统</description>
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ public class StorageStrategyInitCheckAspect {
|
||||
if (currentFileService == null) {
|
||||
throw new StorageStrategyUninitializedException("存储策略尚未初始化, 请联系管理员!");
|
||||
}
|
||||
if (!currentFileService.getIsInitialized()) {
|
||||
if (currentFileService.getIsUnInitialized()) {
|
||||
throw new StorageStrategyUninitializedException("存储策略异常, 请联系管理员!");
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
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;
|
||||
@@ -17,6 +18,7 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 后台管理
|
||||
@@ -46,15 +48,6 @@ public class AdminController {
|
||||
return ResultBean.success(systemConfigDTO);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新系统配置
|
||||
*/
|
||||
@PostMapping("/update-pwd")
|
||||
public ResultBean updatePwd(String username, String password) {
|
||||
systemConfigService.updateUsernameAndPwd(username, password);
|
||||
return ResultBean.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新系统配置
|
||||
*/
|
||||
@@ -72,23 +65,61 @@ public class AdminController {
|
||||
return ResultBean.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改管理员登陆密码
|
||||
*/
|
||||
@PostMapping("/update-pwd")
|
||||
public ResultBean updatePwd(String username, String password) {
|
||||
systemConfigService.updateUsernameAndPwd(username, password);
|
||||
return ResultBean.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定存储引擎的设置
|
||||
* @param storageType 存储引擎
|
||||
* @return 所有设置
|
||||
*/
|
||||
@GetMapping("/strategy-form")
|
||||
public ResultBean getFormByStorageType(StorageTypeEnum storageType) {
|
||||
List<StorageConfig> storageConfigList = storageConfigService.selectStorageConfigByType(storageType);
|
||||
return ResultBean.success(storageConfigList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理当前启用的存储引擎的缓存
|
||||
*/
|
||||
@PostMapping("/clear-cache")
|
||||
public ResultBean clearCache() {
|
||||
@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);
|
||||
|
||||
return ResultBean.success(cacheConfigDTO);
|
||||
}
|
||||
|
||||
@PostMapping("/cache/refresh")
|
||||
public ResultBean refreshCache(String key) throws Exception {
|
||||
AbstractFileService fileService = systemConfigService.getCurrentFileService();
|
||||
fileService.refreshCache(key);
|
||||
return ResultBean.success();
|
||||
}
|
||||
|
||||
@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();
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新存储策略
|
||||
*/
|
||||
@@ -112,4 +143,5 @@ public class AdminController {
|
||||
fileAsyncCacheService.cacheGlobalFile();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -86,7 +86,7 @@ public class FileController {
|
||||
int start = (page - 1) * PAGE_SIZE;
|
||||
int end = page * PAGE_SIZE;
|
||||
end = Math.min(end, total);
|
||||
List<FileItemDTO> fileSubItem = fileItemList.subList(start, end);
|
||||
List<FileItemDTO> fileSubItem = new ArrayList<>(fileItemList.subList(start, end));
|
||||
return ResultBean.successData(fileSubItem);
|
||||
}
|
||||
|
||||
@@ -95,12 +95,32 @@ public class FileController {
|
||||
* @param url 文件路径
|
||||
* @return 文件内容
|
||||
*/
|
||||
@CheckStorageStrategyInit
|
||||
@GetMapping("/content")
|
||||
public ResultBean getContent(String url) {
|
||||
return ResultBean.successData(HttpUtil.getTextContent(url));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取文件类容, 仅限用于, txt, md, ini 等普通文本文件.
|
||||
* @param url 文件路径
|
||||
* @return 文件内容
|
||||
*/
|
||||
@GetMapping("/content/origin")
|
||||
public String getContentOrigin(String url) {
|
||||
return HttpUtil.getTextContent(url);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检测文件是否存在
|
||||
* @param url 文件路径
|
||||
* @return 是否存在
|
||||
*/
|
||||
@GetMapping("/content/exist")
|
||||
public boolean checkFileExist(String url) {
|
||||
return HttpUtil.checkUrlExist(url);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取系统配置信息和当前页的标题, 文件头, 文件尾信息
|
||||
* @param path 路径
|
||||
@@ -115,7 +135,7 @@ public class FileController {
|
||||
|
||||
@CheckStorageStrategyInit
|
||||
@GetMapping("/clearCache")
|
||||
public ResultBean clearCache() {
|
||||
public ResultBean clearCache() throws Exception {
|
||||
AbstractFileService fileService = systemConfigService.getCurrentFileService();
|
||||
if (fileService != null) {
|
||||
fileService.clearCache();
|
||||
|
||||
@@ -7,6 +7,7 @@ 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;
|
||||
@@ -36,6 +37,9 @@ public class InstallController {
|
||||
@Resource
|
||||
private AdminController adminController;
|
||||
|
||||
@Resource
|
||||
private FileAsyncCacheService fileAsyncCacheService;
|
||||
|
||||
@GetMapping("/is-installed")
|
||||
@ResponseBody
|
||||
public ResultBean isInstall() {
|
||||
@@ -79,7 +83,7 @@ public class InstallController {
|
||||
|
||||
@PostMapping("/storage-strategy")
|
||||
@ResponseBody
|
||||
public ResultBean save(@RequestParam Map<String, String> storageStrategyConfig, StorageTypeEnum storageStrategy) {
|
||||
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();
|
||||
@@ -92,6 +96,10 @@ public class InstallController {
|
||||
if (Objects.equals(storageStrategy, currentStorageStrategy)) {
|
||||
AbstractFileService fileService = systemConfigService.getCurrentFileService();
|
||||
fileService.clearCache();
|
||||
|
||||
if (systemConfigService.getEnableCache()) {
|
||||
fileAsyncCacheService.cacheGlobalFile();
|
||||
}
|
||||
fileService.init();
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
package im.zhaojun.common.model.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author zhaojun
|
||||
* @date 2020/1/3 12:39
|
||||
*/
|
||||
@Data
|
||||
public class CacheConfigDTO {
|
||||
private boolean enableCache;
|
||||
private boolean cacheFinish;
|
||||
private Set<String> cacheKeys;
|
||||
}
|
||||
@@ -1,8 +1,11 @@
|
||||
package im.zhaojun.common.service;
|
||||
|
||||
import com.alicp.jetcache.Cache;
|
||||
import com.alicp.jetcache.RefreshPolicy;
|
||||
import com.alicp.jetcache.anno.CacheRefresh;
|
||||
import com.alicp.jetcache.anno.CacheType;
|
||||
import com.alicp.jetcache.anno.Cached;
|
||||
import com.alicp.jetcache.anno.CreateCache;
|
||||
import im.zhaojun.common.model.dto.FileItemDTO;
|
||||
import im.zhaojun.common.model.enums.FileTypeEnum;
|
||||
import im.zhaojun.common.model.enums.StorageTypeEnum;
|
||||
@@ -15,8 +18,11 @@ import javax.annotation.PostConstruct;
|
||||
import javax.annotation.Resource;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author zhaojun
|
||||
@@ -25,6 +31,8 @@ import java.util.concurrent.TimeUnit;
|
||||
@Slf4j
|
||||
public abstract class AbstractFileService implements FileService {
|
||||
|
||||
public static final String SYSTEM_CONFIG_CACHE_PREFIX = "zfile-cache:";
|
||||
|
||||
@Value("${zfile.cache.timeout}")
|
||||
protected Long timeout;
|
||||
|
||||
@@ -33,6 +41,12 @@ public abstract class AbstractFileService implements FileService {
|
||||
@Resource
|
||||
private SystemConfigService systemConfigService;
|
||||
|
||||
@Resource
|
||||
private FileAsyncCacheService fileAsyncCacheService;
|
||||
|
||||
@CreateCache(name = SYSTEM_CONFIG_CACHE_PREFIX, cacheType = CacheType.LOCAL)
|
||||
private Cache<String, List<FileItemDTO>> cache;
|
||||
|
||||
/***
|
||||
* 获取指定路径下的文件及文件夹, 默认缓存 60 分钟,每隔 30 分钟刷新一次.
|
||||
* @param path 文件路径
|
||||
@@ -40,17 +54,20 @@ public abstract class AbstractFileService implements FileService {
|
||||
* @throws Exception 获取文件列表中出现的异常
|
||||
*/
|
||||
@Override
|
||||
@Cached(name = "zfile-cache:",
|
||||
@Cached(name = SYSTEM_CONFIG_CACHE_PREFIX,
|
||||
key = "args[0]",
|
||||
cacheType = CacheType.LOCAL, condition = "mvel{bean('systemConfigService').enableCache}")
|
||||
cacheType = CacheType.LOCAL, localLimit = 100000, condition = "mvel{bean('systemConfigService').enableCache}")
|
||||
@CacheRefresh(refresh = 30, timeUnit = TimeUnit.MINUTES)
|
||||
public abstract List<FileItemDTO> fileList(String path) throws Exception;
|
||||
|
||||
|
||||
/**
|
||||
* 清理当前存储引擎的缓存
|
||||
*/
|
||||
public void clearCache() {
|
||||
public void clearCache() throws Exception {
|
||||
Set<String> cacheKeys = getCacheKeys();
|
||||
cache.removeAll(cacheKeys);
|
||||
closeCacheAutoRefresh();
|
||||
fileAsyncCacheService.setCacheFinish(false);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -72,22 +89,22 @@ public abstract class AbstractFileService implements FileService {
|
||||
|
||||
/**
|
||||
* 获取是否初始化成功
|
||||
* @return 初始化成功与否
|
||||
* @return 初始化成功与否
|
||||
*/
|
||||
public boolean getIsInitialized() {
|
||||
return isInitialized;
|
||||
public boolean getIsUnInitialized() {
|
||||
return !isInitialized;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取存储引擎类型
|
||||
* @return 存储引擎类型枚举
|
||||
* @return 存储引擎类型枚举
|
||||
*/
|
||||
public abstract StorageTypeEnum getStorageTypeEnum();
|
||||
|
||||
/**
|
||||
* 搜索文件
|
||||
* @param name 文件名
|
||||
* @return 包含该文件名的所有文件或文件夹
|
||||
* @param name 文件名
|
||||
* @return 包含该文件名的所有文件或文件夹
|
||||
* @throws Exception 搜索过程出现的异常
|
||||
*/
|
||||
public List<FileItemDTO> search(String name) throws Exception {
|
||||
@@ -104,23 +121,20 @@ public abstract class AbstractFileService implements FileService {
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询所有文件
|
||||
* @return 所有文件
|
||||
* @throws Exception 异常现象
|
||||
* 查询所有文件, 仅去缓存中查询.
|
||||
* @return 所有文件
|
||||
*/
|
||||
public List<FileItemDTO> selectAllFileList() throws Exception {
|
||||
List<FileItemDTO> result = new ArrayList<>();
|
||||
|
||||
boolean enableCache = systemConfigService.getEnableCache();
|
||||
if (!enableCache) {
|
||||
log.debug("未开启缓存, 不支持查询所有文件.");
|
||||
return null;
|
||||
}
|
||||
|
||||
String path = "/";
|
||||
|
||||
FileService currentFileService = (FileService) AopContext.currentProxy();
|
||||
List<FileItemDTO> fileItemList = currentFileService.fileList(path);
|
||||
List<FileItemDTO> fileItemList = cache.get(path);
|
||||
fileItemList = fileItemList == null ? new ArrayList<>() : fileItemList;
|
||||
ArrayDeque<FileItemDTO> queue = new ArrayDeque<>(fileItemList);
|
||||
|
||||
while (!queue.isEmpty()) {
|
||||
@@ -128,10 +142,53 @@ public abstract class AbstractFileService implements FileService {
|
||||
result.add(fileItemDTO);
|
||||
if (fileItemDTO.getType() == FileTypeEnum.FOLDER) {
|
||||
String filePath = StringUtils.removeDuplicateSeparator("/" + fileItemDTO.getPath() + "/" + fileItemDTO.getName() + "/");
|
||||
queue.addAll(currentFileService.fileList(filePath));
|
||||
List<FileItemDTO> cacheList = cache.get(filePath);
|
||||
if (cacheList != null) {
|
||||
queue.addAll(cacheList);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有缓存的 Key, 仅当开启缓存, 且缓存完成时, 可获取.
|
||||
* @return 所有缓存的 Key
|
||||
* @throws Exception 可能出现的异常
|
||||
*/
|
||||
public Set<String> getCacheKeys() throws Exception {
|
||||
if (systemConfigService.getEnableCache() && fileAsyncCacheService.isCacheFinish()) {
|
||||
Set<String> collect = selectAllFileList().stream().map(fileItemDTO -> {
|
||||
if (fileItemDTO.getType() == FileTypeEnum.FOLDER) {
|
||||
return StringUtils.removeDuplicateSeparator("/" + fileItemDTO.getPath() + "/" + fileItemDTO.getName() + "/");
|
||||
}
|
||||
return null;
|
||||
}).collect(Collectors.toSet());
|
||||
collect.remove(null);
|
||||
collect.add("/");
|
||||
return collect;
|
||||
} else {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新缓存
|
||||
*/
|
||||
public void refreshCache(String key) throws Exception {
|
||||
cache.remove(key);
|
||||
FileService currentFileService = (FileService) AopContext.currentProxy();
|
||||
currentFileService.fileList(key);
|
||||
}
|
||||
|
||||
public void closeCacheAutoRefresh() {
|
||||
cache.config().setRefreshPolicy(null);
|
||||
}
|
||||
|
||||
public void openCacheAutoRefresh() {
|
||||
RefreshPolicy refreshPolicy = RefreshPolicy.newPolicy(1, TimeUnit.MINUTES);
|
||||
cache.config().setRefreshPolicy(refreshPolicy);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,12 +1,17 @@
|
||||
package im.zhaojun.common.service;
|
||||
|
||||
import im.zhaojun.common.config.StorageTypeFactory;
|
||||
import im.zhaojun.common.model.dto.FileItemDTO;
|
||||
import im.zhaojun.common.model.enums.FileTypeEnum;
|
||||
import im.zhaojun.common.model.enums.StorageTypeEnum;
|
||||
import im.zhaojun.common.util.StringUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author zhaojun
|
||||
@@ -29,12 +34,35 @@ public class FileAsyncCacheService {
|
||||
return;
|
||||
}
|
||||
|
||||
boolean enableCache = systemConfigService.getEnableCache();
|
||||
if (!enableCache) {
|
||||
log.info("未开启缓存, 跳过启动缓存");
|
||||
return;
|
||||
}
|
||||
|
||||
AbstractFileService fileService = StorageTypeFactory.getStorageTypeService(storageStrategy);
|
||||
|
||||
|
||||
if (fileService.getIsUnInitialized()) {
|
||||
log.info("存储引擎 {} 未初始化成功, 跳过启动缓存.", storageStrategy.getDescription());
|
||||
return;
|
||||
}
|
||||
|
||||
log.info("缓存 {} 所有文件开始", storageStrategy.getDescription());
|
||||
long startTime = System.currentTimeMillis();
|
||||
try {
|
||||
if (fileService.getIsInitialized()) {
|
||||
fileService.selectAllFileList();
|
||||
String path = "/";
|
||||
|
||||
FileService currentFileService = systemConfigService.getCurrentFileService();
|
||||
List<FileItemDTO> fileItemList = currentFileService.fileList(path);
|
||||
ArrayDeque<FileItemDTO> queue = new ArrayDeque<>(fileItemList);
|
||||
|
||||
while (!queue.isEmpty()) {
|
||||
FileItemDTO fileItemDTO = queue.pop();
|
||||
if (fileItemDTO.getType() == FileTypeEnum.FOLDER) {
|
||||
String filePath = StringUtils.removeDuplicateSeparator("/" + fileItemDTO.getPath() + "/" + fileItemDTO.getName() + "/");
|
||||
queue.addAll(currentFileService.fileList(filePath));
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("缓存所有文件失败", e);
|
||||
@@ -45,6 +73,7 @@ public class FileAsyncCacheService {
|
||||
cacheFinish = true;
|
||||
}
|
||||
|
||||
|
||||
public boolean isCacheFinish() {
|
||||
return cacheFinish;
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import java.util.List;
|
||||
public interface FileService {
|
||||
|
||||
/***
|
||||
* 获取指定路径下的文件及文件夹, 默认缓存 60 分钟,每隔 30 分钟刷新一次.
|
||||
* 获取指定路径下的文件及文件夹
|
||||
* @param path 文件路径
|
||||
* @return 文件及文件夹列表
|
||||
* @throws Exception 获取文件列表中出现的异常
|
||||
|
||||
@@ -2,6 +2,7 @@ package im.zhaojun.common.service;
|
||||
|
||||
import cn.hutool.crypto.SecureUtil;
|
||||
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.SystemConfig;
|
||||
@@ -28,7 +29,7 @@ public class SystemConfigService {
|
||||
|
||||
public static final String SYSTEM_CONFIG_CACHE_KEY = "1";
|
||||
|
||||
@CreateCache(name = SYSTEM_CONFIG_CACHE_PREFIX)
|
||||
@CreateCache(name = SYSTEM_CONFIG_CACHE_PREFIX, cacheType = CacheType.LOCAL)
|
||||
private Cache<String, Object> configCache;
|
||||
|
||||
@Resource
|
||||
@@ -135,10 +136,18 @@ public class SystemConfigService {
|
||||
|
||||
systemConfigRepository.saveAll(systemConfigList);
|
||||
|
||||
AbstractFileService currentFileService = getCurrentFileService();
|
||||
|
||||
if (!oldEnableCache && curEnableCache) {
|
||||
log.debug("检测到开启了缓存, 开启预热缓存");
|
||||
currentFileService.openCacheAutoRefresh();
|
||||
fileAsyncCacheService.cacheGlobalFile();
|
||||
}
|
||||
|
||||
if (oldEnableCache && !curEnableCache) {
|
||||
log.debug("检测到关闭了缓存, 正在清理缓存数据及关闭自动刷新");
|
||||
currentFileService.clearCache();
|
||||
}
|
||||
}
|
||||
|
||||
public void updateUsernameAndPwd(String username, String password) {
|
||||
|
||||
@@ -7,6 +7,7 @@ import im.zhaojun.common.util.HttpUtil;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -27,7 +28,7 @@ public class SystemService {
|
||||
SiteConfigDTO siteConfigDTO = new SiteConfigDTO();
|
||||
AbstractFileService fileService = systemConfigService.getCurrentFileService();
|
||||
|
||||
List<FileItemDTO> fileItemList = fileService.fileList(path);
|
||||
List<FileItemDTO> fileItemList = new ArrayList<>(fileService.fileList(path));
|
||||
for (FileItemDTO fileItemDTO : fileItemList) {
|
||||
if (ZFileConstant.FOOTER_FILE_NAME.equalsIgnoreCase(fileItemDTO.getName())) {
|
||||
siteConfigDTO.setFooter(HttpUtil.getTextContent(fileItemDTO.getUrl()));
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package im.zhaojun.common.util;
|
||||
|
||||
import org.springframework.web.client.RestClientException;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
/**
|
||||
@@ -13,4 +14,15 @@ public class HttpUtil {
|
||||
return result == null ? "" : result;
|
||||
}
|
||||
|
||||
public static boolean checkUrlExist(String url) {
|
||||
RestTemplate restTemplate = SpringContextHolder.getBean(RestTemplate.class);
|
||||
try {
|
||||
restTemplate.headForHeaders(url);
|
||||
return true;
|
||||
} catch (RestClientException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
.el-menu[data-v-11c58ddb],.el-row[data-v-11c58ddb]{height:100vh}
|
||||
1
src/main/resources/static/css/adminIndex.67225c93.css
Normal file
1
src/main/resources/static/css/adminIndex.67225c93.css
Normal file
@@ -0,0 +1 @@
|
||||
.el-menu[data-v-4fea46ab],.el-row[data-v-4fea46ab]{height:100vh}
|
||||
File diff suppressed because one or more lines are too long
1
src/main/resources/static/css/app.46f70347.css
Normal file
1
src/main/resources/static/css/app.46f70347.css
Normal file
File diff suppressed because one or more lines are too long
1
src/main/resources/static/css/chunk-vendors.b9a3d604.css
Normal file
1
src/main/resources/static/css/chunk-vendors.b9a3d604.css
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
|
||||
.login-container[data-v-ec97d092]{width:100%;height:100%}.login-page[data-v-ec97d092]{border-radius:5px;margin:180px auto;width:350px;padding:35px 35px 15px;background:#fff;border:1px solid #eaeaea;-webkit-box-shadow:0 0 25px #cac6c6;box-shadow:0 0 25px #cac6c6}label.el-checkbox.rememberme[data-v-ec97d092]{margin:0 0 15px;text-align:left}
|
||||
@@ -1 +0,0 @@
|
||||
#siteForm[data-v-5ab4a46c]{margin-top:20px;margin-left:20px}#siteForm[data-v-5ab4a46c] .el-select{width:100%}.zfile-word-aux[data-v-5ab4a46c]{margin-left:20px;color:#aaa}
|
||||
@@ -1 +0,0 @@
|
||||
#storageForm[data-v-4e200950]{margin-left:20px}#storageForm[data-v-4e200950] .el-select{width:100%}.el-tabs[data-v-1b7d7bc8]{display:block;width:940px}
|
||||
@@ -1 +0,0 @@
|
||||
#pwdForm[data-v-7d080185]{margin-top:20px;margin-left:20px}
|
||||
@@ -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.6656b315.css rel=prefetch><link href=/css/install.39da241e.css rel=prefetch><link href=/css/login.4c106b9d.css rel=prefetch><link href=/css/siteSetting.8aa8fb90.css rel=prefetch><link href=/css/storageStrategy.c619bd5e.css rel=prefetch><link href=/css/updatePassword.11e9911c.css rel=prefetch><link href=/js/adminIndex.52ec74b4.js rel=prefetch><link href=/js/dplayer.acc587f7.js rel=prefetch><link href=/js/flv.4f294571.js rel=prefetch><link href=/js/highlight.1e643364.js rel=prefetch><link href=/js/install.fa590583.js rel=prefetch><link href=/js/login.c6d3d33e.js rel=prefetch><link href=/js/marked.58818bc3.js rel=prefetch><link href=/js/siteSetting.2fa65c09.js rel=prefetch><link href=/js/storageStrategy.ec7b4260.js rel=prefetch><link href=/js/updatePassword.2cc74208.js rel=prefetch><link href=/css/app.2293f0bd.css rel=preload as=style><link href=/css/chunk-vendors.f095837b.css rel=preload as=style><link href=/js/app.11d51f1c.js rel=preload as=script><link href=/js/chunk-vendors.eec3a6bb.js rel=preload as=script><link href=/css/chunk-vendors.f095837b.css rel=stylesheet><link href=/css/app.2293f0bd.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.eec3a6bb.js></script><script src=/js/app.11d51f1c.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.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>
|
||||
@@ -1 +1 @@
|
||||
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["adminIndex"],{"76fb":function(t,e,a){"use strict";var s=a("efec"),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("修改密码")])])],1)],1),a("el-col",{attrs:{span:12}},[a("keep-alive",[a("router-view")],1)],1)],1)},i=[],n={name:"Index",data:function(){return{active:"/admin/storage"}}},l=n,r=(a("76fb"),a("2877")),o=Object(r["a"])(l,s,i,!1,null,"11c58ddb",null);e["default"]=o.exports},efec:function(t,e,a){}}]);
|
||||
(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
1
src/main/resources/static/js/app.362c49b5.js
Normal file
1
src/main/resources/static/js/app.362c49b5.js
Normal file
File diff suppressed because one or more lines are too long
141
src/main/resources/static/js/chunk-vendors.10f10391.js
Normal file
141
src/main/resources/static/js/chunk-vendors.10f10391.js
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1
src/main/resources/static/js/install.3ac7201f.js
Normal file
1
src/main/resources/static/js/install.3ac7201f.js
Normal file
@@ -0,0 +1 @@
|
||||
(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}}]);
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user