mirror of
https://github.com/zfile-dev/zfile.git
synced 2025-04-19 05:34:52 +00:00
Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
84e9cce60f | ||
|
|
5720bd93ec | ||
|
|
bcae9713bc | ||
|
|
04e3023071 | ||
|
|
a09ef84629 | ||
|
|
1d29395191 | ||
|
|
3720dc6aa9 | ||
|
|
3ada172be2 | ||
|
|
15f8fbb49b | ||
|
|
547e688d38 | ||
|
|
708eb33d0e | ||
|
|
e954b725b1 | ||
|
|
c89cb4e495 | ||
|
|
286e9775f6 | ||
|
|
60513abe6a | ||
|
|
f7a8c9faa2 | ||
|
|
55e0d32ef8 | ||
|
|
4c0bacba31 | ||
|
|
61128f2677 | ||
|
|
3866526b95 | ||
|
|
250955fac9 |
71
README.md
71
README.md
@@ -23,8 +23,9 @@
|
||||
* 文件夹密码
|
||||
* 支持在线浏览文本文件, 视频, 图片, 音乐. (支持 FLV 和 HLS)
|
||||
* 文件/目录二维码
|
||||
* 缓存动态开启, 缓存自动刷新
|
||||
* 全局搜索
|
||||
* 缓存动态开启, ~~缓存自动刷新 (v2.2 及以前版本支持)~~
|
||||
* ~~全局搜索 (v2.2 及以前版本支持)~~
|
||||
* 同时挂载多个存储策略
|
||||
* 支持 阿里云 OSS, FTP, 华为云 OBS, 本地存储, MINIO, OneDrive 国际/家庭/个人版, OneDrive 世纪互联版, 七牛云 KODO, 腾讯云 COS, 又拍云 USS.
|
||||
|
||||
## 快速开始
|
||||
@@ -34,14 +35,26 @@
|
||||
```bash
|
||||
# CentOS系统
|
||||
yum install -y java-1.8.0-openjdk unzip
|
||||
```
|
||||
|
||||
# Debian/Ubuntu系统
|
||||
```bash
|
||||
# Debian 9 / Ubuntu 14+
|
||||
apt update
|
||||
apt install -y openjdk-8-jre-headless unzip
|
||||
```
|
||||
|
||||
```bash
|
||||
# Debian 10 (Buster) 系统
|
||||
apt update && apt install -y apt-transport-https software-properties-common ca-certificates dirmngr gnupg
|
||||
wget -qO - https://adoptopenjdk.jfrog.io/adoptopenjdk/api/gpg/key/public | apt-key add -
|
||||
add-apt-repository --yes https://adoptopenjdk.jfrog.io/adoptopenjdk/deb/
|
||||
apt update && apt install -y adoptopenjdk-8-hotspot-jre
|
||||
```
|
||||
|
||||
|
||||
> 如为更新程序, 则请先执行 `~/zfile/bin/stop.sh && rm -rf ~/zfile` 清理旧程序. 首次安装请忽略此选项.
|
||||
|
||||
|
||||
下载项目:
|
||||
|
||||
```bash
|
||||
@@ -51,6 +64,8 @@ mkdir zfile && unzip zfile-release.war -d zfile && rm -rf zfile-release.war
|
||||
chmod +x zfile/bin/*.sh
|
||||
```
|
||||
|
||||
> 下载指定版本可以将 `zfile-release.war` 改为 `zfile-x.x.war`,如 `zfile-2.2.war`。
|
||||
|
||||
程序的目录结构为:
|
||||
```
|
||||
├── zfile
|
||||
@@ -68,7 +83,7 @@ chmod +x zfile/bin/*.sh
|
||||
~/zfile/bin/start.sh
|
||||
```
|
||||
|
||||
篇幅有限, 更详细的安装教程请参考: [安装文档](http://zhaojun.im/zfile-install)
|
||||
篇幅有限, 更详细的安装教程及介绍请参考: [ZFile 文档](http://zhaojun.im/zfile-install)
|
||||
|
||||
访问地址:
|
||||
|
||||
@@ -79,46 +94,25 @@ chmod +x zfile/bin/*.sh
|
||||
管理后台: http://127.0.0.1:8080/#/admin
|
||||
|
||||
|
||||
## OneDrive 使用教程.
|
||||
|
||||
访问地址进行授权, 获取 accessToken 和 refreshToken:
|
||||
|
||||
|
||||
国际/家庭/个人版:
|
||||
|
||||
https://login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id=09939809-c617-43c8-a220-a93c1513c5d4&response_type=code&redirect_uri=https://zfile.jun6.net/onedrive/callback&scope=offline_access%20User.Read%20Files.ReadWrite.All
|
||||
|
||||
|
||||
世纪互联版:
|
||||
|
||||
https://login.chinacloudapi.cn/common/oauth2/v2.0/authorize?client_id=4a72d927-1907-488d-9eb2-1b465c53c1c5&response_type=code&redirect_uri=https://zfile.jun6.net/onedrive/china-callback&scope=offline_access%20User.Read%20Files.ReadWrite.All
|
||||
|
||||
|
||||
然后分别填写至访问令牌和刷新令牌即可:
|
||||
|
||||

|
||||
|
||||
## 运行环境
|
||||
|
||||
* JDK: `1.8`
|
||||
* 数据库: `h2/mysql`
|
||||
|
||||
## 预览
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
## 常见问题
|
||||
|
||||
### 数据库
|
||||
|
||||
缓存默认支持 `h2` 和 `mysql`, 前者为嵌入式数据库, 无需安装, 但后者相对性能更好.
|
||||
|
||||
### 默认路径
|
||||
|
||||
默认 H2 数据库文件地址: `~/.zfile/db/`, `~` 表示用户目录, windows 为 `C:/Users/用户名/`, linux 为 `/home/用户名/`, root 用户为 `/root/`
|
||||
默认 H2 数据库文件地址: `~/.zfile/db/`, `~` 表示用户目录
|
||||
|
||||
windows 为 `C:/Users/用户名/`
|
||||
|
||||
linux 为 `/home/用户名/`, root 用户为 `/root/`
|
||||
|
||||
> 2.3 及以后版本路径为 `~/.zfile-new/db/`
|
||||
|
||||
### 文档文件和加密文件
|
||||
|
||||
@@ -133,19 +127,18 @@ https://login.chinacloudapi.cn/common/oauth2/v2.0/authorize?client_id=4a72d927-1
|
||||
- [x] 后台优化 - 设置按照其功能进行分离
|
||||
- [x] 体验优化 - 支持前后端分离部署
|
||||
- [x] 体验优化 - 文本预览更换 vscode 同款编辑器 monaco editor
|
||||
- [x] 新功能 - Docker 支持
|
||||
- [x] 架构调整 - 支持多存储策略
|
||||
- [ ] 新功能 - 后台支持上传、编辑、删除等操作
|
||||
- [ ] 新功能 - WebDav 支持
|
||||
- [ ] 新功能 - Docker 支持
|
||||
- [ ] 新功能 - 离线下载 (aria2)
|
||||
- [ ] 体验优化 - 忽略文件列表 (正则表达式)
|
||||
- [ ] 体验优化 - 自定义支持预览的文件后缀 (正则表达式)
|
||||
- [ ] 架构调整 - 支持多存储策略
|
||||
- [ ] 体验优化 - 一键安装脚本
|
||||
|
||||
## 支持作者
|
||||
|
||||
如果本项目对你有帮助,请作者喝杯咖啡吧。
|
||||
|
||||
|
||||
<img src="http://cdn.jun6.net/alipay.png" width="200" height="312">
|
||||
<img src="http://cdn.jun6.net/wechat.png" width="222" height="300">
|
||||
|
||||
2
pom.xml
2
pom.xml
@@ -12,7 +12,7 @@
|
||||
|
||||
<groupId>im.zhaojun</groupId>
|
||||
<artifactId>zfile</artifactId>
|
||||
<version>2.2</version>
|
||||
<version>2.6</version>
|
||||
<name>zfile</name>
|
||||
<packaging>war</packaging>
|
||||
<description>一个在线的文件浏览系统</description>
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
package im.zhaojun.zfile.core;
|
||||
package im.zhaojun.zfile.aspect;
|
||||
|
||||
import im.zhaojun.zfile.cache.ZFileCache;
|
||||
import im.zhaojun.zfile.model.dto.FileItemDTO;
|
||||
import im.zhaojun.zfile.service.SystemConfigService;
|
||||
import im.zhaojun.zfile.model.entity.DriveConfig;
|
||||
import im.zhaojun.zfile.service.DriveConfigService;
|
||||
import im.zhaojun.zfile.service.base.AbstractBaseFileService;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
@@ -24,28 +25,41 @@ public class FileListCacheAop {
|
||||
private ZFileCache zFileCache;
|
||||
|
||||
@Resource
|
||||
private SystemConfigService systemConfigService;
|
||||
private DriveConfigService driveConfigService;
|
||||
|
||||
|
||||
/**
|
||||
* 缓存切面, 如果此驱动器开启了缓存, 则从缓存中取数据, 没有开启, 则直接调用方法.
|
||||
*/
|
||||
@Around(value = "execution(public * im.zhaojun.zfile.service.base.AbstractBaseFileService.fileList(..))")
|
||||
public Object around(ProceedingJoinPoint point) throws Throwable {
|
||||
List<FileItemDTO> result;
|
||||
|
||||
// 获取请求路径
|
||||
Object[] args = point.getArgs();
|
||||
String path = String.valueOf(args[0]);
|
||||
|
||||
boolean enableCache = systemConfigService.getEnableCache();
|
||||
// 获取当前驱动器
|
||||
AbstractBaseFileService fileService = ((AbstractBaseFileService) point.getTarget());
|
||||
Integer driveId = fileService.driveId;
|
||||
|
||||
// 判断驱动器是否开启了缓存
|
||||
DriveConfig driveConfig = driveConfigService.findById(driveId);
|
||||
boolean enableCache = driveConfig.getEnableCache();
|
||||
|
||||
if (enableCache) {
|
||||
List<FileItemDTO> cacheFileList = zFileCache.get(path);
|
||||
if (CollectionUtils.isEmpty(cacheFileList)) {
|
||||
List<FileItemDTO> cacheFileList = zFileCache.get(driveId, path);
|
||||
if (cacheFileList == null) {
|
||||
result = (List<FileItemDTO>) point.proceed();
|
||||
zFileCache.put(path, result);
|
||||
zFileCache.put(driveId, path, result);
|
||||
} else {
|
||||
result = cacheFileList;
|
||||
}
|
||||
} else {
|
||||
result = (List<FileItemDTO>) point.proceed();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
230
src/main/java/im/zhaojun/zfile/cache/ZFileCache.java
vendored
230
src/main/java/im/zhaojun/zfile/cache/ZFileCache.java
vendored
@@ -1,50 +1,137 @@
|
||||
package im.zhaojun.zfile.cache;
|
||||
|
||||
import cn.hutool.cache.CacheUtil;
|
||||
import cn.hutool.cache.impl.CacheObj;
|
||||
import cn.hutool.cache.impl.TimedCache;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import im.zhaojun.zfile.model.constant.ZFileConstant;
|
||||
import im.zhaojun.zfile.model.dto.FileItemDTO;
|
||||
import im.zhaojun.zfile.model.dto.SystemConfigDTO;
|
||||
import im.zhaojun.zfile.model.entity.DriveConfig;
|
||||
import im.zhaojun.zfile.repository.DriverConfigRepository;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.*;
|
||||
import javax.annotation.Resource;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
/**
|
||||
* ZFile 缓存类
|
||||
*
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Component
|
||||
public class ZFileCache {
|
||||
|
||||
private ConcurrentMap<String, List<FileItemDTO>> fileCache = new ConcurrentHashMap<>();
|
||||
@Value("${zfile.cache.timeout}")
|
||||
private long timeout;
|
||||
|
||||
|
||||
/**
|
||||
* 缓存 map 对象.
|
||||
*
|
||||
* ConcurrentMap<Integer, ConcurrentHashMap<String, List<FileItemDTO>>>
|
||||
* ConcurrentMap<driveId, ConcurrentHashMap<key, value>>
|
||||
*
|
||||
* driveId: 驱动器 ID
|
||||
* key: 文件夹路径
|
||||
* value: 文件夹中内容
|
||||
*/
|
||||
private ConcurrentMap<Integer, TimedCache<String, List<FileItemDTO>>> drivesCache = new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* 系统设置缓存
|
||||
*/
|
||||
private SystemConfigDTO systemConfigCache;
|
||||
|
||||
public Date lastCacheAutoRefreshDate;
|
||||
@Resource
|
||||
private DriverConfigRepository driverConfigRepository;
|
||||
|
||||
public synchronized void put(String key, List<FileItemDTO> value) {
|
||||
fileCache.put(key, value);
|
||||
|
||||
/**
|
||||
* 写入缓存
|
||||
*
|
||||
* @param driveId
|
||||
* 驱动器 ID
|
||||
*
|
||||
* @param key
|
||||
* 文件夹路径
|
||||
*
|
||||
* @param value
|
||||
* 文件夹中列表
|
||||
*/
|
||||
public synchronized void put(Integer driveId, String key, List<FileItemDTO> value) {
|
||||
getCacheByDriveId(driveId).put(key, value);
|
||||
}
|
||||
|
||||
public List<FileItemDTO> get(String key) {
|
||||
return fileCache.get(key);
|
||||
|
||||
/**
|
||||
* 获取指定驱动器, 某个文件夹的名称
|
||||
*
|
||||
* @param driveId
|
||||
* 驱动器 ID
|
||||
*
|
||||
* @param key
|
||||
* 文件夹路径
|
||||
*
|
||||
* @return 驱动器中文件夹的内容
|
||||
*/
|
||||
public List<FileItemDTO> get(Integer driveId, String key) {
|
||||
return getCacheByDriveId(driveId).get(key, false);
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
fileCache.clear();
|
||||
|
||||
/**
|
||||
* 清空指定驱动器的缓存.
|
||||
*
|
||||
* @param driveId
|
||||
* 驱动器 ID
|
||||
*/
|
||||
public void clear(Integer driveId) {
|
||||
getCacheByDriveId(driveId).clear();
|
||||
}
|
||||
|
||||
public int cacheCount() {
|
||||
return fileCache.size();
|
||||
|
||||
/**
|
||||
* 获取指定驱动器中已缓存文件夹数量
|
||||
*
|
||||
* @param driveId
|
||||
* 驱动器 ID
|
||||
*
|
||||
* @return 已缓存文件夹数量
|
||||
*/
|
||||
public int cacheCount(Integer driveId) {
|
||||
return getCacheByDriveId(driveId).size();
|
||||
}
|
||||
|
||||
public List<FileItemDTO> find(String key, boolean ignoreCase, boolean searchContainEncryptedFile) {
|
||||
|
||||
/**
|
||||
* 指定驱动器, 根据文件及文件名查找相关的文件
|
||||
*
|
||||
* @param driveId
|
||||
* 驱动器 ID
|
||||
*
|
||||
* @param key
|
||||
* 搜索键, 可匹配文件夹名称和文件名称.
|
||||
*
|
||||
* @return 搜索结果, 包含文件夹和文件.
|
||||
*/
|
||||
public List<FileItemDTO> find(Integer driveId, String key) {
|
||||
List<FileItemDTO> result = new ArrayList<>();
|
||||
|
||||
Collection<List<FileItemDTO>> values = fileCache.values();
|
||||
for (List<FileItemDTO> fileItemList : values) {
|
||||
DriveConfig driveConfig = driverConfigRepository.getOne(driveId);
|
||||
boolean searchContainEncryptedFile = driveConfig.getSearchContainEncryptedFile();
|
||||
boolean ignoreCase = driveConfig.getSearchIgnoreCase();
|
||||
|
||||
// 如果开启了 "搜索包含加密文件" 选项, 则直接返回 true.
|
||||
for (List<FileItemDTO> fileItemList : getCacheByDriveId(driveId)) {
|
||||
// 过滤加密文件
|
||||
if (!searchContainEncryptedFile && isEncryptedFolder(fileItemList)) {
|
||||
continue;
|
||||
}
|
||||
@@ -52,6 +139,7 @@ public class ZFileCache {
|
||||
for (FileItemDTO fileItemDTO : fileItemList) {
|
||||
boolean testResult;
|
||||
|
||||
// 根据是否需要忽略大小写来匹配文件(夹)名
|
||||
if (ignoreCase) {
|
||||
testResult = StrUtil.containsIgnoreCase(fileItemDTO.getName(), key);
|
||||
} else {
|
||||
@@ -66,39 +154,73 @@ public class ZFileCache {
|
||||
return result;
|
||||
}
|
||||
|
||||
public Set<String> keySet() {
|
||||
return fileCache.keySet();
|
||||
}
|
||||
|
||||
public void remove(String key) {
|
||||
fileCache.remove(key);
|
||||
}
|
||||
|
||||
public void updateConfig(SystemConfigDTO systemConfigCache) {
|
||||
this.systemConfigCache = systemConfigCache;
|
||||
}
|
||||
|
||||
public SystemConfigDTO getConfig() {
|
||||
return this.systemConfigCache;
|
||||
}
|
||||
|
||||
public void removeConfig() {
|
||||
this.systemConfigCache = null;
|
||||
}
|
||||
|
||||
public Date getLastCacheAutoRefreshDate() {
|
||||
return lastCacheAutoRefreshDate;
|
||||
}
|
||||
|
||||
public void setLastCacheAutoRefreshDate(Date lastCacheAutoRefreshDate) {
|
||||
this.lastCacheAutoRefreshDate = lastCacheAutoRefreshDate;
|
||||
/**
|
||||
* 获取所有缓存 key (文件夹名称)
|
||||
*
|
||||
* @return 所有缓存 key
|
||||
*/
|
||||
public Set<String> keySet(Integer driveId) {
|
||||
Iterator<CacheObj<String, List<FileItemDTO>>> cacheObjIterator = getCacheByDriveId(driveId).cacheObjIterator();
|
||||
Set<String> keys = new HashSet<>();
|
||||
while (cacheObjIterator.hasNext()) {
|
||||
keys.add(cacheObjIterator.next().getKey());
|
||||
}
|
||||
return keys;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 不是加密文件夹
|
||||
* @param list 文件夹中的内容
|
||||
* @return 返回此文件夹是否加密.
|
||||
* 从缓存中删除指定存储器的某个路径的缓存
|
||||
*
|
||||
* @param driveId
|
||||
* 驱动器 ID
|
||||
*
|
||||
* @param key
|
||||
* 文件夹路径
|
||||
*/
|
||||
public void remove(Integer driveId, String key) {
|
||||
getCacheByDriveId(driveId).remove(key);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 更新缓存中的系统设置
|
||||
*
|
||||
* @param systemConfigCache
|
||||
* 系统设置
|
||||
*/
|
||||
public void updateConfig(SystemConfigDTO systemConfigCache) {
|
||||
this.systemConfigCache = systemConfigCache;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 从缓存中获取系统设置
|
||||
*
|
||||
* @return 系统设置
|
||||
*/
|
||||
public SystemConfigDTO getConfig() {
|
||||
return this.systemConfigCache;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 清空系统设置缓存
|
||||
*/
|
||||
public void removeConfig() {
|
||||
this.systemConfigCache = null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 判断此文件夹是否为加密文件夹 (包含)
|
||||
*
|
||||
* @param list
|
||||
* 文件夹中的内容
|
||||
*
|
||||
* @return 返回此文件夹是否是加密的 ().
|
||||
*/
|
||||
private boolean isEncryptedFolder(List<FileItemDTO> list) {
|
||||
// 遍历文件判断是否包含
|
||||
@@ -109,4 +231,24 @@ public class ZFileCache {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取指定驱动器对应的缓存
|
||||
*
|
||||
* @param driveId
|
||||
* 驱动器 ID
|
||||
*
|
||||
* @return 驱动器对应的缓存
|
||||
*/
|
||||
private synchronized TimedCache<String, List<FileItemDTO>> getCacheByDriveId(Integer driveId) {
|
||||
TimedCache<String, List<FileItemDTO>> driveCache = drivesCache.get(driveId);
|
||||
if (driveCache == null) {
|
||||
driveCache = CacheUtil.newTimedCache(timeout * 1000);
|
||||
drivesCache.put(driveId, driveCache);
|
||||
}
|
||||
|
||||
return driveCache;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
package im.zhaojun.zfile.config;
|
||||
|
||||
import im.zhaojun.zfile.model.dto.FileItemDTO;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
/**
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Configuration
|
||||
public class CacheConfig {
|
||||
|
||||
@Bean
|
||||
public ConcurrentMap<String, List<FileItemDTO>> concurrentMapCache() {
|
||||
return new ConcurrentHashMap<>();
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package im.zhaojun.zfile.config;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpRequest;
|
||||
import org.springframework.http.client.ClientHttpRequestExecution;
|
||||
import org.springframework.http.client.ClientHttpRequestInterceptor;
|
||||
import org.springframework.http.client.ClientHttpResponse;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
|
||||
/**
|
||||
* @author zhaojun
|
||||
*/
|
||||
public class ContentTypeTextToTextJson implements ClientHttpRequestInterceptor {
|
||||
|
||||
@Override
|
||||
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution)
|
||||
throws IOException {
|
||||
ClientHttpResponse response = execution.execute(request, body);
|
||||
HttpHeaders headers = response.getHeaders();
|
||||
headers.put("Content-Type", Collections.singletonList("application/text"));
|
||||
return response;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,81 +0,0 @@
|
||||
package im.zhaojun.zfile.config;
|
||||
|
||||
import im.zhaojun.zfile.model.enums.StorageTypeEnum;
|
||||
import im.zhaojun.zfile.service.SystemConfigService;
|
||||
import im.zhaojun.zfile.service.base.AbstractBaseFileService;
|
||||
import im.zhaojun.zfile.service.impl.OneDriveChinaServiceImpl;
|
||||
import im.zhaojun.zfile.service.impl.OneDriveServiceImpl;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Configuration
|
||||
@EnableScheduling
|
||||
@Slf4j
|
||||
public class GlobalScheduleTask {
|
||||
|
||||
@Resource
|
||||
private OneDriveServiceImpl oneDriveServiceImpl;
|
||||
|
||||
@Resource
|
||||
private OneDriveChinaServiceImpl oneDriveChinaServiceImpl;
|
||||
|
||||
@Resource
|
||||
private SystemConfigService systemConfigService;
|
||||
|
||||
/**
|
||||
* 项目启动 30 秒后, 每 15 分钟执行一次刷新 OneDrive Token 的定时任务.
|
||||
*/
|
||||
@Scheduled(fixedRate = 1000 * 60 * 10, initialDelay = 1000 * 30)
|
||||
public void autoRefreshOneDriveToken() {
|
||||
|
||||
try {
|
||||
log.debug("尝试调用 OneDrive 自动刷新 AccessToken 定时任务");
|
||||
|
||||
AbstractBaseFileService currentFileService = systemConfigService.getCurrentFileService();
|
||||
|
||||
if (!(currentFileService instanceof OneDriveServiceImpl
|
||||
|| currentFileService instanceof OneDriveChinaServiceImpl)) {
|
||||
log.debug("当前启用存储类型, 不是 OneDrive, 跳过自动刷新 AccessToken");
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentFileService.getIsUnInitialized()) {
|
||||
log.debug("当前启用 OneDrive 未初始化成功, 跳过自动刷新 AccessToken");
|
||||
return;
|
||||
}
|
||||
|
||||
StorageTypeEnum currentStorageTypeEnum = currentFileService.getStorageTypeEnum();
|
||||
|
||||
try {
|
||||
refreshOneDriveToken(currentStorageTypeEnum);
|
||||
} catch (Exception e) {
|
||||
log.debug("刷新 " + currentStorageTypeEnum.getDescription() + " Token 失败.", e);
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
log.debug("尝试调用 OneDrive 自动刷新 AccessToken 定时任务出现未知异常", e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 调用刷新 OneDrive Token
|
||||
*/
|
||||
public void refreshOneDriveToken(StorageTypeEnum storageType) {
|
||||
if (Objects.equals(storageType, StorageTypeEnum.ONE_DRIVE_CHINA)) {
|
||||
oneDriveChinaServiceImpl.refreshOneDriveToken();
|
||||
} else {
|
||||
oneDriveServiceImpl.refreshOneDriveToken();
|
||||
}
|
||||
log.info("刷新 {} key 时间: {}", storageType.getDescription(), LocalDateTime.now());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,19 +1,20 @@
|
||||
package im.zhaojun.zfile.config;
|
||||
|
||||
import im.zhaojun.zfile.model.entity.StorageConfig;
|
||||
import im.zhaojun.zfile.model.constant.StorageConfigConstant;
|
||||
import im.zhaojun.zfile.model.entity.StorageConfig;
|
||||
import im.zhaojun.zfile.model.enums.StorageTypeEnum;
|
||||
import im.zhaojun.zfile.service.StorageConfigService;
|
||||
import im.zhaojun.zfile.service.impl.OneDriveChinaServiceImpl;
|
||||
import im.zhaojun.zfile.service.impl.OneDriveServiceImpl;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.client.ClientHttpRequestInterceptor;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
|
||||
/**
|
||||
* @author zhaojun
|
||||
@@ -25,30 +26,25 @@ public class OneDriveConfig {
|
||||
private StorageConfigService storageConfigService;
|
||||
|
||||
@Resource
|
||||
@Lazy
|
||||
private OneDriveServiceImpl oneDriveServiceImpl;
|
||||
|
||||
@Resource
|
||||
@Lazy
|
||||
private OneDriveChinaServiceImpl oneDriveChinaServiceImpl;
|
||||
|
||||
|
||||
/**
|
||||
* OneDrive 请求 RestTemplate, 会在请求头中添加 Bearer: Authorization {token} 信息, 用于 API 认证.
|
||||
*/
|
||||
@Bean
|
||||
public RestTemplate oneDriveRestTemplate() {
|
||||
RestTemplate restTemplate = new RestTemplate();
|
||||
|
||||
ClientHttpRequestInterceptor interceptor = (httpRequest, bytes, clientHttpRequestExecution) -> {
|
||||
String host = httpRequest.getURI().getHost();
|
||||
StorageTypeEnum type;
|
||||
if (oneDriveChinaServiceImpl.getGraphEndPoint().contains(host)) {
|
||||
type = StorageTypeEnum.ONE_DRIVE_CHINA;
|
||||
} else if (oneDriveServiceImpl.getGraphEndPoint().contains(host)) {
|
||||
type = StorageTypeEnum.ONE_DRIVE;
|
||||
} else {
|
||||
return clientHttpRequestExecution.execute(httpRequest, bytes);
|
||||
}
|
||||
HttpHeaders headers = httpRequest.getHeaders();
|
||||
Integer driveId = Integer.valueOf(((LinkedList)headers.get("driveId")).get(0).toString());
|
||||
|
||||
StorageConfig accessTokenConfig =
|
||||
storageConfigService.selectByTypeAndKey(type, StorageConfigConstant.ACCESS_TOKEN_KEY);
|
||||
storageConfigService.findByDriveIdAndKey(driveId, StorageConfigConstant.ACCESS_TOKEN_KEY);
|
||||
|
||||
String tokenValue = String.format("%s %s", "Bearer", accessTokenConfig.getValue());
|
||||
httpRequest.getHeaders().add("Authorization", tokenValue);
|
||||
@@ -58,4 +54,4 @@ public class OneDriveConfig {
|
||||
return restTemplate;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -22,10 +22,13 @@ public class WebMvcConfig implements WebMvcConfigurer {
|
||||
@Bean
|
||||
public ServletWebServerFactory webServerFactory() {
|
||||
TomcatServletWebServerFactory webServerFactory = new TomcatServletWebServerFactory();
|
||||
|
||||
// 添加对 URL 中特殊符号的支持.
|
||||
webServerFactory.addConnectorCustomizers(connector -> {
|
||||
connector.setAttribute("relaxedPathChars", "<>[\\]^`{|}");
|
||||
connector.setAttribute("relaxedQueryChars", "<>[\\]^`{|}");
|
||||
});
|
||||
return webServerFactory;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,6 +2,8 @@ package im.zhaojun.zfile.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.client.ClientHttpResponse;
|
||||
import org.springframework.http.converter.StringHttpMessageConverter;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
@@ -18,7 +20,14 @@ public class ZFileConfiguration {
|
||||
public RestTemplate restTemplate(){
|
||||
RestTemplate restTemplate = new RestTemplate();
|
||||
restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
|
||||
restTemplate.setInterceptors(Collections.singletonList(new ContentTypeTextToTextJson()));
|
||||
|
||||
restTemplate.setInterceptors(Collections.singletonList((request, body, execution) -> {
|
||||
ClientHttpResponse response = execution.execute(request, body);
|
||||
HttpHeaders headers = response.getHeaders();
|
||||
headers.put("Content-Type", Collections.singletonList("application/text"));
|
||||
return response;
|
||||
}));
|
||||
|
||||
return restTemplate;
|
||||
}
|
||||
|
||||
|
||||
107
src/main/java/im/zhaojun/zfile/context/DriveContext.java
Normal file
107
src/main/java/im/zhaojun/zfile/context/DriveContext.java
Normal file
@@ -0,0 +1,107 @@
|
||||
package im.zhaojun.zfile.context;
|
||||
|
||||
import im.zhaojun.zfile.model.entity.DriveConfig;
|
||||
import im.zhaojun.zfile.model.enums.StorageTypeEnum;
|
||||
import im.zhaojun.zfile.service.DriveConfigService;
|
||||
import im.zhaojun.zfile.service.base.AbstractBaseFileService;
|
||||
import im.zhaojun.zfile.util.SpringContextHolder;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.annotation.DependsOn;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* 驱动器上下文环境
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Component
|
||||
@DependsOn("springContextHolder")
|
||||
public class DriveContext implements ApplicationContextAware {
|
||||
|
||||
private static Map<Integer, AbstractBaseFileService> drivesServiceMap = new ConcurrentHashMap<>();
|
||||
|
||||
private static Map<StorageTypeEnum, Class<AbstractBaseFileService>> storageTypeEnumClassMap = new ConcurrentHashMap<>();
|
||||
|
||||
@Resource
|
||||
private DriveConfigService driveConfigService;
|
||||
|
||||
|
||||
/**
|
||||
* 初始化指定驱动器的 Service, 添加到上下文环境中.
|
||||
*
|
||||
* @param driveId
|
||||
* 驱动器 ID.
|
||||
*/
|
||||
public void initDrive(Integer driveId) {
|
||||
AbstractBaseFileService baseFileService = getBeanByDriveId(driveId);
|
||||
if (baseFileService != null) {
|
||||
baseFileService.init(driveId);
|
||||
drivesServiceMap.put(driveId, baseFileService);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取指定驱动器的 Service.
|
||||
*
|
||||
* @param driveId
|
||||
* 驱动器 ID
|
||||
*
|
||||
* @return 驱动器对应的 Service
|
||||
*/
|
||||
public AbstractBaseFileService getDriveService(Integer driveId) {
|
||||
return drivesServiceMap.get(driveId);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 销毁指定驱动器的 Service.
|
||||
*
|
||||
* @param driveId
|
||||
* 驱动器 ID
|
||||
*/
|
||||
public void destroyDrive(Integer driveId) {
|
||||
drivesServiceMap.remove(driveId);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取指定驱动器对应的 Service, 状态为未初始化
|
||||
*
|
||||
* @param driveId
|
||||
* 驱动器 ID
|
||||
*
|
||||
* @return 驱动器对应未初始化的 Service
|
||||
*/
|
||||
private AbstractBaseFileService getBeanByDriveId(Integer driveId) {
|
||||
StorageTypeEnum storageTypeEnum = driveConfigService.findStorageTypeById(driveId);
|
||||
Map<String, AbstractBaseFileService> beansOfType = SpringContextHolder.getBeansOfType(AbstractBaseFileService.class);
|
||||
for (AbstractBaseFileService value : beansOfType.values()) {
|
||||
if (Objects.equals(value.getStorageTypeEnum(), storageTypeEnum)) {
|
||||
return SpringContextHolder.getBean(value.getClass());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 项目启动时, 自动调用所有驱动器进行初始化.
|
||||
*/
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
List<DriveConfig> list = driveConfigService.list();
|
||||
for (DriveConfig driveConfig : list) {
|
||||
initDrive(driveConfig.getId());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package im.zhaojun.zfile.config;
|
||||
package im.zhaojun.zfile.context;
|
||||
|
||||
import im.zhaojun.zfile.model.enums.StorageTypeEnum;
|
||||
import im.zhaojun.zfile.service.base.AbstractBaseFileService;
|
||||
@@ -6,19 +6,21 @@ import org.springframework.beans.BeansException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
/**
|
||||
* 存储类型工厂类
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Component
|
||||
public class StorageTypeFactory implements ApplicationContextAware {
|
||||
public class StorageTypeContext implements ApplicationContextAware {
|
||||
|
||||
private static Map<String, AbstractBaseFileService> storageTypeEnumFileServiceMap;
|
||||
|
||||
private static ApplicationContext applicationContext;
|
||||
|
||||
|
||||
/**
|
||||
* 项目启动时执行
|
||||
*/
|
||||
@@ -30,6 +32,7 @@ public class StorageTypeFactory implements ApplicationContextAware {
|
||||
storageTypeEnumFileServiceMap = act.getBeansOfType(AbstractBaseFileService.class);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取指定存储类型 Service
|
||||
*/
|
||||
@@ -44,7 +47,9 @@ public class StorageTypeFactory implements ApplicationContextAware {
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
public static ApplicationContext getApplicationContext() {
|
||||
return applicationContext;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,200 +0,0 @@
|
||||
package im.zhaojun.zfile.controller;
|
||||
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.util.ZipUtil;
|
||||
import im.zhaojun.zfile.config.StorageTypeFactory;
|
||||
import im.zhaojun.zfile.model.dto.ResultBean;
|
||||
import im.zhaojun.zfile.model.dto.StorageStrategyDTO;
|
||||
import im.zhaojun.zfile.model.dto.SystemConfigDTO;
|
||||
import im.zhaojun.zfile.model.entity.StorageConfig;
|
||||
import im.zhaojun.zfile.model.enums.StorageTypeEnum;
|
||||
import im.zhaojun.zfile.model.support.SystemMonitorInfo;
|
||||
import im.zhaojun.zfile.service.StorageConfigService;
|
||||
import im.zhaojun.zfile.service.SystemConfigService;
|
||||
import im.zhaojun.zfile.service.base.AbstractBaseFileService;
|
||||
import im.zhaojun.zfile.service.support.FileAsyncCacheService;
|
||||
import im.zhaojun.zfile.util.FileUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
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 javax.servlet.http.HttpServletResponse;
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 后台管理
|
||||
* @author zhaojun
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/admin")
|
||||
public class AdminController {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(AdminController.class);
|
||||
|
||||
@Resource
|
||||
private StorageConfigService storageConfigService;
|
||||
|
||||
@Resource
|
||||
private SystemConfigService systemConfigService;
|
||||
|
||||
@Resource
|
||||
private FileAsyncCacheService fileAsyncCacheService;
|
||||
|
||||
/**
|
||||
* 获取系统配置
|
||||
*/
|
||||
@GetMapping("/config")
|
||||
public ResultBean getConfig() {
|
||||
SystemConfigDTO systemConfigDTO = systemConfigService.getSystemConfig();
|
||||
return ResultBean.success(systemConfigDTO);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新系统配置
|
||||
*/
|
||||
@PostMapping("/config")
|
||||
public ResultBean updateConfig(SystemConfigDTO systemConfigDTO) throws Exception {
|
||||
StorageTypeEnum currentStorageStrategy = systemConfigService.getCurrentStorageStrategy();
|
||||
if (!Objects.equals(currentStorageStrategy, systemConfigDTO.getStorageStrategy())) {
|
||||
if (systemConfigService.getEnableCache()) {
|
||||
return ResultBean.error("不支持缓存开启状态下, 切换存储策略, 请先手动关闭缓存");
|
||||
}
|
||||
log.info("已将存储策略由 {} 切换为 {}",
|
||||
currentStorageStrategy.getDescription(),
|
||||
systemConfigDTO.getStorageStrategy().getDescription());
|
||||
refreshStorageStrategy();
|
||||
}
|
||||
|
||||
systemConfigDTO.setId(1);
|
||||
systemConfigService.updateSystemConfig(systemConfigDTO);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回支持的存储引擎.
|
||||
*/
|
||||
@GetMapping("/support-strategy")
|
||||
public ResultBean supportStrategy() {
|
||||
List<StorageStrategyDTO> result = new ArrayList<>();
|
||||
StorageTypeEnum[] values = StorageTypeEnum.values();
|
||||
for (StorageTypeEnum value : values) {
|
||||
AbstractBaseFileService storageTypeService = StorageTypeFactory.getStorageTypeService(value);
|
||||
result.add(new StorageStrategyDTO(value.getKey(),
|
||||
value.getDescription(),
|
||||
storageTypeService.getIsInitialized()));
|
||||
}
|
||||
return ResultBean.successData(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存存储策略
|
||||
* @param storageStrategyConfig 保存表单值
|
||||
* @param storageStrategy 所属策略
|
||||
* @return 操作结果
|
||||
*/
|
||||
@PostMapping("/storage-strategy")
|
||||
public ResultBean save(@RequestParam Map<String, String> storageStrategyConfig, StorageTypeEnum storageStrategy) {
|
||||
// 保存设置.
|
||||
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);
|
||||
|
||||
// 获取当前修改的存储策略 Service, 尝试调用初始化.
|
||||
AbstractBaseFileService updateStorageStrategyService = StorageTypeFactory.getStorageTypeService(storageStrategy);
|
||||
updateStorageStrategyService.init();
|
||||
|
||||
// 如果修改的为当前启用的缓存, 则重新进行缓存.
|
||||
StorageTypeEnum currentStorageStrategy = systemConfigService.getCurrentStorageStrategy();
|
||||
if (Objects.equals(storageStrategy, currentStorageStrategy)) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("检测到更新了当前启用的存储策略 {}, 已清理缓存.", currentStorageStrategy);
|
||||
}
|
||||
|
||||
AbstractBaseFileService fileService = systemConfigService.getCurrentFileService();
|
||||
fileService.clearFileCache();
|
||||
fileAsyncCacheService.cacheGlobalFile();
|
||||
}
|
||||
|
||||
// 返回是否初始化成功.
|
||||
if (updateStorageStrategyService.getIsInitialized()) {
|
||||
return ResultBean.success();
|
||||
} else {
|
||||
return ResultBean.error("保存成功, 但尝试初始化异常, 请检查设置.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新存储策略
|
||||
*/
|
||||
public void refreshStorageStrategy() {
|
||||
StorageTypeEnum storageStrategy = systemConfigService.getCurrentStorageStrategy();
|
||||
refreshStorageStrategy(storageStrategy);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新存储策略
|
||||
*/
|
||||
private void refreshStorageStrategy(StorageTypeEnum storageStrategy) {
|
||||
if (storageStrategy == null) {
|
||||
log.info("尚未配置存储策略.");
|
||||
} else {
|
||||
AbstractBaseFileService fileService = systemConfigService.getCurrentFileService();
|
||||
fileService.init();
|
||||
fileService.clearFileCache();
|
||||
log.info("切换至存储类型: {}", storageStrategy.getDescription());
|
||||
fileAsyncCacheService.cacheGlobalFile();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 系统日志下载
|
||||
*/
|
||||
@GetMapping("/log")
|
||||
public ResponseEntity<Object> downloadLog(HttpServletResponse response) {
|
||||
String userHome = System.getProperty("user.home");
|
||||
File fileZip = ZipUtil.zip(userHome + "/.zfile/logs");
|
||||
String currentDate = DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss");
|
||||
return FileUtil.export(fileZip, "ZFile 诊断日志 - " + currentDate + ".zip");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取系统监控信息
|
||||
*/
|
||||
@GetMapping("monitor")
|
||||
public ResultBean monitor() {
|
||||
return ResultBean.success(new SystemMonitorInfo());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
package im.zhaojun.zfile.controller;
|
||||
|
||||
import im.zhaojun.zfile.cache.ZFileCache;
|
||||
import im.zhaojun.zfile.model.dto.CacheConfigDTO;
|
||||
import im.zhaojun.zfile.model.dto.ResultBean;
|
||||
import im.zhaojun.zfile.service.SystemConfigService;
|
||||
import im.zhaojun.zfile.service.base.AbstractBaseFileService;
|
||||
import im.zhaojun.zfile.service.support.FileAsyncCacheService;
|
||||
import im.zhaojun.zfile.service.support.FileCacheService;
|
||||
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;
|
||||
|
||||
/**
|
||||
* @author zhaojun
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/admin/cache")
|
||||
public class CacheController {
|
||||
|
||||
@Resource
|
||||
private SystemConfigService systemConfigService;
|
||||
|
||||
@Resource
|
||||
private FileAsyncCacheService fileAsyncCacheService;
|
||||
|
||||
@Resource
|
||||
private FileCacheService fileCacheService;
|
||||
|
||||
@Resource
|
||||
private ZFileCache zFileCache;
|
||||
|
||||
@PostMapping("/enable")
|
||||
public ResultBean enableCache() {
|
||||
fileCacheService.enableCache();
|
||||
return ResultBean.success();
|
||||
}
|
||||
|
||||
@PostMapping("/disable")
|
||||
public ResultBean disableCache() {
|
||||
fileCacheService.disableCache();
|
||||
return ResultBean.success();
|
||||
}
|
||||
|
||||
@GetMapping("/config")
|
||||
public ResultBean cacheConfig() {
|
||||
CacheConfigDTO cacheConfigDTO = new CacheConfigDTO();
|
||||
cacheConfigDTO.setEnableCache(systemConfigService.getEnableCache());
|
||||
cacheConfigDTO.setCacheFinish(fileAsyncCacheService.isCacheFinish());
|
||||
cacheConfigDTO.setCacheKeys(zFileCache.keySet());
|
||||
cacheConfigDTO.setCacheDirectoryCount(zFileCache.cacheCount());
|
||||
cacheConfigDTO.setLastCacheAutoRefreshDate(zFileCache.getLastCacheAutoRefreshDate());
|
||||
return ResultBean.success(cacheConfigDTO);
|
||||
}
|
||||
|
||||
|
||||
@PostMapping("/refresh")
|
||||
public ResultBean refreshCache(String key) throws Exception {
|
||||
AbstractBaseFileService fileService = systemConfigService.getCurrentFileService();
|
||||
fileService.refreshCache(key);
|
||||
return ResultBean.success();
|
||||
}
|
||||
|
||||
/*
|
||||
@PostMapping("/clear")
|
||||
public ResultBean clearCache(String key) {
|
||||
AbstractFileService fileService = systemConfigService.getCurrentFileService();
|
||||
fileService.clearFileCache();
|
||||
return ResultBean.success();
|
||||
}
|
||||
|
||||
|
||||
@PostMapping("/all")
|
||||
public ResultBean cacheAll() {
|
||||
AbstractFileService fileService = systemConfigService.getCurrentFileService();
|
||||
fileService.clearFileCache();
|
||||
fileAsyncCacheService.cacheGlobalFile();
|
||||
return ResultBean.success();
|
||||
}
|
||||
*/
|
||||
}
|
||||
@@ -9,21 +9,32 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* 公共 Controller
|
||||
* @author zhaojun
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/common")
|
||||
public class CommonController {
|
||||
|
||||
|
||||
/**
|
||||
* 返回系统支持的所有存储策略
|
||||
*
|
||||
* @return 存储策略
|
||||
*/
|
||||
@GetMapping("/support-strategy")
|
||||
public ResultBean supportStrategy() {
|
||||
return ResultBean.successData(StorageTypeEnum.values());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取文件内容, 仅限用于, txt, md, ini 等普通文本文件.
|
||||
* @param url 文件路径
|
||||
* @return 文件内容
|
||||
* 获取文件内容, 仅限用于 txt, md, ini 等普通文本文件.
|
||||
*
|
||||
* @param url
|
||||
* 文件路径
|
||||
*
|
||||
* @return 文件内容
|
||||
*/
|
||||
@GetMapping("/content")
|
||||
public ResultBean getContent(String url) {
|
||||
@@ -31,35 +42,17 @@ public class CommonController {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取文件内容, 仅限用于, 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 url 文件 URL
|
||||
* @return 音频信息, 标题封面等信息
|
||||
*
|
||||
* @param url
|
||||
* 文件 URL
|
||||
*
|
||||
* @return 音频信息, 标题封面等信息
|
||||
*/
|
||||
@GetMapping("/audio-info")
|
||||
public ResultBean getAudioInfo(String url) throws Exception {
|
||||
return ResultBean.success(AudioHelper.getAudioInfo(url));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,31 +1,31 @@
|
||||
package im.zhaojun.zfile.controller;
|
||||
|
||||
import cn.hutool.core.util.BooleanUtil;
|
||||
import cn.hutool.core.util.URLUtil;
|
||||
import im.zhaojun.zfile.model.annotation.CheckStorageStrategyInit;
|
||||
import im.zhaojun.zfile.exception.SearchDisableException;
|
||||
import im.zhaojun.zfile.model.support.FilePageModel;
|
||||
import im.zhaojun.zfile.model.constant.ZFileConstant;
|
||||
import im.zhaojun.zfile.model.dto.FileItemDTO;
|
||||
import im.zhaojun.zfile.model.dto.ResultBean;
|
||||
import im.zhaojun.zfile.model.dto.SiteConfigDTO;
|
||||
import im.zhaojun.zfile.model.dto.SystemConfigDTO;
|
||||
import im.zhaojun.zfile.service.base.AbstractBaseFileService;
|
||||
import im.zhaojun.zfile.service.support.FileAsyncCacheService;
|
||||
import im.zhaojun.zfile.model.dto.SystemFrontConfigDTO;
|
||||
import im.zhaojun.zfile.model.support.FilePageModel;
|
||||
import im.zhaojun.zfile.service.DriveConfigService;
|
||||
import im.zhaojun.zfile.service.SystemConfigService;
|
||||
import im.zhaojun.zfile.service.SystemService;
|
||||
import im.zhaojun.zfile.service.base.AbstractBaseFileService;
|
||||
import im.zhaojun.zfile.context.DriveContext;
|
||||
import im.zhaojun.zfile.util.FileComparator;
|
||||
import im.zhaojun.zfile.util.HttpUtil;
|
||||
import im.zhaojun.zfile.util.StringUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.client.HttpClientErrorException;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 前台文件管理
|
||||
@@ -36,34 +36,61 @@ import java.util.*;
|
||||
@RestController
|
||||
public class FileController {
|
||||
|
||||
@Resource
|
||||
private SystemService systemService;
|
||||
|
||||
@Resource
|
||||
private SystemConfigService systemConfigService;
|
||||
|
||||
@Resource
|
||||
private FileAsyncCacheService fileAsyncCacheService;
|
||||
private DriveContext driveContext;
|
||||
|
||||
@Resource
|
||||
private DriveConfigService driveConfigService;
|
||||
|
||||
/**
|
||||
* 滚动加载每页条数.
|
||||
*/
|
||||
private static final Integer PAGE_SIZE = 30;
|
||||
|
||||
@CheckStorageStrategyInit
|
||||
@GetMapping("/list")
|
||||
public ResultBean list(@RequestParam(defaultValue = "/") String path,
|
||||
@RequestParam(defaultValue = "name") String sortBy,
|
||||
@RequestParam(defaultValue = "asc") String order,
|
||||
|
||||
/**
|
||||
* 获取所有驱动器
|
||||
*
|
||||
* @return 所有驱动器
|
||||
*/
|
||||
@GetMapping("/drive/list")
|
||||
public ResultBean drives() {
|
||||
return ResultBean.success(driveConfigService.list());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取某个驱动器下, 指定路径的数据, 每页固定 {@link #PAGE_SIZE} 条数据.
|
||||
*
|
||||
* @param driveId
|
||||
* 驱动器 ID
|
||||
*
|
||||
* @param path
|
||||
* 路径
|
||||
*
|
||||
* @param password
|
||||
* 文件夹密码, 某些文件夹需要密码才能访问, 当不需要密码时, 此参数可以为空
|
||||
*
|
||||
* @param page
|
||||
* 页数
|
||||
*
|
||||
* @return 当前路径下所有文件及文件夹
|
||||
*/
|
||||
@GetMapping("/list/{driveId}")
|
||||
public ResultBean list(@PathVariable(name = "driveId") Integer driveId,
|
||||
@RequestParam(defaultValue = "/") String path,
|
||||
@RequestParam(required = false) String password,
|
||||
@RequestParam(defaultValue = "1") Integer page) throws Exception {
|
||||
AbstractBaseFileService fileService = systemConfigService.getCurrentFileService();
|
||||
AbstractBaseFileService fileService = driveContext.getDriveService(driveId);
|
||||
List<FileItemDTO> fileItemList = fileService.fileList(StringUtils.removeDuplicateSeparator("/" + path + "/"));
|
||||
|
||||
for (FileItemDTO fileItemDTO : fileItemList) {
|
||||
if (ZFileConstant.PASSWORD_FILE_NAME.equals(fileItemDTO.getName())) {
|
||||
String expectedPasswordContent;
|
||||
try {
|
||||
expectedPasswordContent = HttpUtil.getTextContent(fileItemDTO.getUrl() + '1');
|
||||
expectedPasswordContent = HttpUtil.getTextContent(fileItemDTO.getUrl());
|
||||
} catch (HttpClientErrorException httpClientErrorException) {
|
||||
log.debug("尝试重新获取密码文件缓存中链接后仍失败", httpClientErrorException);
|
||||
try {
|
||||
@@ -86,45 +113,50 @@ public class FileController {
|
||||
return ResultBean.error("此文件夹需要密码.", ResultBean.REQUIRED_PASSWORD);
|
||||
}
|
||||
}
|
||||
|
||||
return ResultBean.successData(getSortedPagingData(fileItemList, page));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取系统配置信息和当前页的标题, 页面文档信息
|
||||
* @param path 路径
|
||||
*
|
||||
* @param driveId
|
||||
* 驱动器 ID
|
||||
*
|
||||
* @return 返回指定存储器的系统配置信息
|
||||
*/
|
||||
@CheckStorageStrategyInit
|
||||
@GetMapping("/config")
|
||||
public ResultBean getConfig(String path) throws Exception {
|
||||
SiteConfigDTO config = systemService.getConfig(StringUtils.removeDuplicateSeparator("/" + path + "/"));
|
||||
config.setSystemConfigDTO(systemConfigService.getSystemConfig());
|
||||
return ResultBean.successData(config);
|
||||
@GetMapping("/config/{driveId}")
|
||||
public ResultBean getConfig(@PathVariable(name = "driveId") Integer driveId, String path) {
|
||||
SystemFrontConfigDTO systemConfig = systemConfigService.getSystemFrontConfig(driveId);
|
||||
|
||||
AbstractBaseFileService fileService = driveContext.getDriveService(driveId);
|
||||
String fullPath = StringUtils.removeDuplicateSeparator(path + "/" + ZFileConstant.README_FILE_NAME);
|
||||
try {
|
||||
FileItemDTO fileItem = fileService.getFileItem(fullPath);
|
||||
String readme = HttpUtil.getTextContent(fileItem.getUrl());
|
||||
systemConfig.setReadme(readme);
|
||||
} catch (Exception e) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
return ResultBean.successData(systemConfig);
|
||||
}
|
||||
|
||||
|
||||
@CheckStorageStrategyInit
|
||||
@GetMapping("/search")
|
||||
@GetMapping("/search/{driveId}")
|
||||
public ResultBean search(@RequestParam(value = "name", defaultValue = "/") String name,
|
||||
@RequestParam(defaultValue = "name") String sortBy,
|
||||
@RequestParam(defaultValue = "asc") String order,
|
||||
@RequestParam(defaultValue = "1") Integer page) {
|
||||
AbstractBaseFileService fileService = systemConfigService.getCurrentFileService();
|
||||
SystemConfigDTO systemConfigDTO = systemConfigService.getSystemConfig();
|
||||
if (BooleanUtil.isFalse(systemConfigDTO.getSearchEnable())) {
|
||||
throw new SearchDisableException("搜索功能未开启");
|
||||
}
|
||||
if (!fileAsyncCacheService.isCacheFinish()) {
|
||||
throw new SearchDisableException("搜索功能缓存预热中, 请稍后再试");
|
||||
}
|
||||
List<FileItemDTO> fileItemList = fileService.search(URLUtil.decode(name));
|
||||
return ResultBean.successData(getSortedPagingData(fileItemList, page));
|
||||
@RequestParam(defaultValue = "1") Integer page,
|
||||
@PathVariable("driveId") Integer driveId) {
|
||||
return ResultBean.error("暂不支持搜索功能");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 过滤文件列表, 不显示密码, 文档文件.
|
||||
* 过滤文件列表, 去除密码, 文档文件.
|
||||
*
|
||||
* @param fileItemList
|
||||
* 文件列表
|
||||
*/
|
||||
private void filterFileList(List<FileItemDTO> fileItemList) {
|
||||
if (fileItemList == null) {
|
||||
@@ -136,6 +168,17 @@ public class FileController {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 对传入的文件列表, 按照文件名进行排序, 然后取相应页数的文件
|
||||
*
|
||||
* @param fileItemList
|
||||
* 文件列表
|
||||
*
|
||||
* @param page
|
||||
* 要取的页数
|
||||
*
|
||||
* @return 排序及分页后的那段数据
|
||||
*/
|
||||
private FilePageModel getSortedPagingData(List<FileItemDTO> fileItemList, Integer page) {
|
||||
ArrayList<FileItemDTO> copy = new ArrayList<>(Arrays.asList(new FileItemDTO[fileItemList.size()]));
|
||||
Collections.copy(copy, fileItemList);
|
||||
@@ -148,25 +191,30 @@ public class FileController {
|
||||
int totalPage = (total + PAGE_SIZE - 1) / PAGE_SIZE;
|
||||
|
||||
if (page > totalPage) {
|
||||
return new FilePageModel(total, totalPage, Collections.emptyList());
|
||||
return new FilePageModel(totalPage, Collections.emptyList());
|
||||
}
|
||||
|
||||
int start = (page - 1) * PAGE_SIZE;
|
||||
int end = page * PAGE_SIZE;
|
||||
end = Math.min(end, total);
|
||||
return new FilePageModel(total, totalPage, copy.subList(start, end));
|
||||
return new FilePageModel(totalPage, copy.subList(start, end));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取指定路径下的文件信息内容
|
||||
* @param path 文件全路径
|
||||
* @return 该文件的名称, 路径, 大小, 下载地址等信息.
|
||||
*
|
||||
* @param driveId
|
||||
* 驱动器 ID
|
||||
*
|
||||
* @param path
|
||||
* 文件全路径
|
||||
*
|
||||
* @return 该文件的名称, 路径, 大小, 下载地址等信息.
|
||||
*/
|
||||
@CheckStorageStrategyInit
|
||||
@GetMapping("/directlink")
|
||||
public ResultBean directlink(String path) {
|
||||
AbstractBaseFileService fileService = systemConfigService.getCurrentFileService();
|
||||
@GetMapping("/directlink/{driveId}")
|
||||
public ResultBean directlink(@PathVariable(name = "driveId") Integer driveId, String path) {
|
||||
AbstractBaseFileService fileService = driveContext.getDriveService(driveId);
|
||||
return ResultBean.successData(fileService.getFileItem(path));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,20 +1,17 @@
|
||||
package im.zhaojun.zfile.controller;
|
||||
|
||||
import cn.hutool.crypto.SecureUtil;
|
||||
import im.zhaojun.zfile.model.entity.StorageConfig;
|
||||
import im.zhaojun.zfile.model.dto.InstallModelDTO;
|
||||
import im.zhaojun.zfile.controller.admin.AdminController;
|
||||
import im.zhaojun.zfile.model.dto.ResultBean;
|
||||
import im.zhaojun.zfile.model.dto.SystemConfigDTO;
|
||||
import im.zhaojun.zfile.model.enums.StorageTypeEnum;
|
||||
import im.zhaojun.zfile.service.StorageConfigService;
|
||||
import im.zhaojun.zfile.service.SystemConfigService;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 系统安装初始化
|
||||
@@ -34,50 +31,23 @@ public class InstallController {
|
||||
|
||||
@GetMapping("/is-installed")
|
||||
public ResultBean isInstall() {
|
||||
if (systemConfigService.getCurrentStorageStrategy() == null) {
|
||||
return ResultBean.success();
|
||||
if (!StringUtils.isEmpty(systemConfigService.getAdminUsername())) {
|
||||
return ResultBean.error("请勿重复初始化");
|
||||
}
|
||||
return ResultBean.error("请勿重复初始化");
|
||||
}
|
||||
|
||||
|
||||
@PostMapping("/install")
|
||||
public ResultBean install(InstallModelDTO installModelDTO) throws Exception {
|
||||
SystemConfigDTO systemConfigDTO = systemConfigService.getSystemConfig();
|
||||
|
||||
if (systemConfigDTO.getStorageStrategy() != null) {
|
||||
return ResultBean.error("请勿重复初始化.");
|
||||
}
|
||||
|
||||
systemConfigDTO.setSiteName(installModelDTO.getSiteName());
|
||||
StorageTypeEnum storageTypeEnum = installModelDTO.getStorageStrategy();
|
||||
systemConfigDTO.setStorageStrategy(storageTypeEnum);
|
||||
systemConfigDTO.setUsername(installModelDTO.getUsername());
|
||||
systemConfigDTO.setPassword(SecureUtil.md5(installModelDTO.getPassword()));
|
||||
systemConfigDTO.setDomain(installModelDTO.getDomain());
|
||||
systemConfigService.updateSystemConfig(systemConfigDTO);
|
||||
|
||||
Map<String, String> storageStrategyConfig = installModelDTO.getStorageStrategyConfig();
|
||||
|
||||
List<StorageConfig> storageConfigList = storageConfigService.selectStorageConfigByType(storageTypeEnum);
|
||||
for (StorageConfig storageConfig : storageConfigList) {
|
||||
String key = storageConfig.getKey();
|
||||
String value = storageStrategyConfig.get(key);
|
||||
storageConfig.setValue(value);
|
||||
}
|
||||
|
||||
storageConfigService.updateStorageConfig(storageConfigList);
|
||||
adminController.refreshStorageStrategy();
|
||||
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);
|
||||
@PostMapping("/install")
|
||||
public ResultBean install(SystemConfigDTO systemConfigDTO) {
|
||||
if (!StringUtils.isEmpty(systemConfigService.getAdminUsername())) {
|
||||
return ResultBean.error("请勿重复初始化.");
|
||||
}
|
||||
|
||||
systemConfigDTO.setPassword(SecureUtil.md5(systemConfigDTO.getPassword()));
|
||||
systemConfigService.updateSystemConfig(systemConfigDTO);
|
||||
|
||||
return ResultBean.success();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,12 +1,14 @@
|
||||
package im.zhaojun.zfile.controller;
|
||||
|
||||
import im.zhaojun.zfile.service.impl.LocalServiceImpl;
|
||||
import im.zhaojun.zfile.context.DriveContext;
|
||||
import im.zhaojun.zfile.util.FileUtil;
|
||||
import im.zhaojun.zfile.util.StringUtils;
|
||||
import im.zhaojun.zfile.service.impl.LocalServiceImpl;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.util.AntPathMatcher;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.servlet.HandlerMapping;
|
||||
|
||||
@@ -15,23 +17,33 @@ import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* 本地存储 Controller
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Controller
|
||||
public class LocalController {
|
||||
|
||||
@Resource
|
||||
private LocalServiceImpl localServiceImpl;
|
||||
private DriveContext driveContext;
|
||||
|
||||
@GetMapping("/file/**")
|
||||
/**
|
||||
* 本地存储下载指定文件
|
||||
*
|
||||
* @param driveId
|
||||
* 驱动器 ID
|
||||
*
|
||||
* @return 文件
|
||||
*/
|
||||
@GetMapping("/file/{driveId}/**")
|
||||
@ResponseBody
|
||||
public ResponseEntity<Object> downAttachment(final HttpServletRequest request) {
|
||||
public ResponseEntity<Object> downAttachment(@PathVariable("driveId") Integer driveId, final HttpServletRequest request) {
|
||||
String path = (String) request.getAttribute(
|
||||
HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE);
|
||||
String bestMatchPattern = (String) request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE);
|
||||
AntPathMatcher apm = new AntPathMatcher();
|
||||
String filePath = apm.extractPathWithinPattern(bestMatchPattern, path);
|
||||
|
||||
return FileUtil.export(new File(StringUtils.concatPath(localServiceImpl.getFilePath(), filePath)));
|
||||
LocalServiceImpl localService = (LocalServiceImpl) driveContext.getDriveService(driveId);
|
||||
return FileUtil.export(new File(StringUtils.concatPath(localService.getFilePath(), filePath)));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
package im.zhaojun.zfile.controller;
|
||||
|
||||
import im.zhaojun.zfile.service.impl.OneDriveChinaServiceImpl;
|
||||
import im.zhaojun.zfile.model.support.OneDriveToken;
|
||||
import im.zhaojun.zfile.service.impl.OneDriveChinaServiceImpl;
|
||||
import im.zhaojun.zfile.service.impl.OneDriveServiceImpl;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
@@ -24,7 +24,7 @@ public class OneDriveController {
|
||||
private OneDriveChinaServiceImpl oneDriveChinaServiceImpl;
|
||||
|
||||
@GetMapping("/callback")
|
||||
public String onedriveCallback(String code, Model model) {
|
||||
public String oneDriveCallback(String code, Model model) {
|
||||
OneDriveToken oneDriveToken = oneDriveServiceImpl.getToken(code);
|
||||
model.addAttribute("accessToken", oneDriveToken.getAccessToken());
|
||||
model.addAttribute("refreshToken", oneDriveToken.getRefreshToken());
|
||||
@@ -33,7 +33,7 @@ public class OneDriveController {
|
||||
|
||||
|
||||
@GetMapping("/china-callback")
|
||||
public String onedriveChinaCallback(String code, Model model) {
|
||||
public String oneDriveChinaCallback(String code, Model model) {
|
||||
OneDriveToken oneDriveToken = oneDriveChinaServiceImpl.getToken(code);
|
||||
model.addAttribute("accessToken", oneDriveToken.getAccessToken());
|
||||
model.addAttribute("refreshToken", oneDriveToken.getRefreshToken());
|
||||
|
||||
@@ -4,11 +4,12 @@ import cn.hutool.core.util.URLUtil;
|
||||
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.service.SystemConfigService;
|
||||
import im.zhaojun.zfile.service.base.AbstractBaseFileService;
|
||||
import im.zhaojun.zfile.context.DriveContext;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.util.AntPathMatcher;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.servlet.HandlerMapping;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
@@ -17,16 +18,22 @@ import java.util.Objects;
|
||||
|
||||
/**
|
||||
* @author Zhao Jun
|
||||
* 2020/2/9 11:17
|
||||
*/
|
||||
@Controller
|
||||
public class PageController {
|
||||
|
||||
@Resource
|
||||
private SystemConfigService systemConfigService;
|
||||
private DriveContext driveContext;
|
||||
|
||||
@GetMapping("/directlink/**")
|
||||
public String directlink(final HttpServletRequest request) {
|
||||
/**
|
||||
* 获取指定驱动器, 某个文件的直链, 然后重定向过去.
|
||||
* @param driveId
|
||||
* 驱动器 ID
|
||||
*
|
||||
* @return 重定向至文件直链
|
||||
*/
|
||||
@GetMapping("/directlink/{driveId}/**")
|
||||
public String directlink(@PathVariable("driveId") Integer driveId, final HttpServletRequest request) {
|
||||
String path = (String) request.getAttribute(
|
||||
HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE);
|
||||
String bestMatchPattern = (String) request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE);
|
||||
@@ -37,7 +44,7 @@ public class PageController {
|
||||
filePath = "/" + filePath;
|
||||
}
|
||||
|
||||
AbstractBaseFileService fileService = systemConfigService.getCurrentFileService();
|
||||
AbstractBaseFileService fileService = driveContext.getDriveService(driveId);
|
||||
FileItemDTO fileItem = fileService.getFileItem(filePath);
|
||||
|
||||
String url = fileItem.getUrl();
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
package im.zhaojun.zfile.controller.admin;
|
||||
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.util.ZipUtil;
|
||||
import im.zhaojun.zfile.context.StorageTypeContext;
|
||||
import im.zhaojun.zfile.model.dto.ResultBean;
|
||||
import im.zhaojun.zfile.model.dto.StorageStrategyDTO;
|
||||
import im.zhaojun.zfile.model.dto.SystemConfigDTO;
|
||||
import im.zhaojun.zfile.model.entity.StorageConfig;
|
||||
import im.zhaojun.zfile.model.enums.StorageTypeEnum;
|
||||
import im.zhaojun.zfile.model.support.SystemMonitorInfo;
|
||||
import im.zhaojun.zfile.service.SystemConfigService;
|
||||
import im.zhaojun.zfile.service.base.AbstractBaseFileService;
|
||||
import im.zhaojun.zfile.util.FileUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
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 javax.servlet.http.HttpServletResponse;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 管理后台接口
|
||||
* @author zhaojun
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/admin")
|
||||
@Slf4j
|
||||
public class AdminController {
|
||||
|
||||
@Resource
|
||||
private SystemConfigService systemConfigService;
|
||||
|
||||
/**
|
||||
* 获取系统配置
|
||||
*/
|
||||
@GetMapping("/config")
|
||||
public ResultBean getConfig() {
|
||||
SystemConfigDTO systemConfigDTO = systemConfigService.getSystemConfig();
|
||||
return ResultBean.success(systemConfigDTO);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 更新系统配置
|
||||
*/
|
||||
@PostMapping("/config")
|
||||
public ResultBean updateConfig(SystemConfigDTO systemConfigDTO) throws Exception {
|
||||
systemConfigDTO.setId(1);
|
||||
systemConfigService.updateSystemConfig(systemConfigDTO);
|
||||
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) {
|
||||
AbstractBaseFileService storageTypeService = StorageTypeContext.getStorageTypeService(storageType);
|
||||
List<StorageConfig> storageConfigList = storageTypeService.storageStrategyConfigList();
|
||||
return ResultBean.success(storageConfigList);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 返回支持的存储引擎.
|
||||
*/
|
||||
@GetMapping("/support-strategy")
|
||||
public ResultBean supportStrategy() {
|
||||
List<StorageStrategyDTO> result = new ArrayList<>();
|
||||
StorageTypeEnum[] values = StorageTypeEnum.values();
|
||||
return ResultBean.successData(values);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 系统日志下载
|
||||
*/
|
||||
@GetMapping("/log")
|
||||
public ResponseEntity<Object> downloadLog(HttpServletResponse response) {
|
||||
String userHome = System.getProperty("user.home");
|
||||
File fileZip = ZipUtil.zip(userHome + "/.zfile/logs");
|
||||
String currentDate = DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss");
|
||||
return FileUtil.export(fileZip, "ZFile 诊断日志 - " + currentDate + ".zip");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取系统监控信息
|
||||
*/
|
||||
@GetMapping("monitor")
|
||||
public ResultBean monitor() {
|
||||
return ResultBean.success(new SystemMonitorInfo());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package im.zhaojun.zfile.controller.admin;
|
||||
|
||||
import im.zhaojun.zfile.model.dto.ResultBean;
|
||||
import im.zhaojun.zfile.service.DriveConfigService;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
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;
|
||||
|
||||
/**
|
||||
* 缓存 Controller
|
||||
*
|
||||
* @author zhaojun
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/admin/cache")
|
||||
public class CacheController {
|
||||
|
||||
@Resource
|
||||
private DriveConfigService driveConfigService;
|
||||
|
||||
|
||||
@PostMapping("/{driveId}/enable")
|
||||
public ResultBean enableCache(@PathVariable("driveId") Integer driveId) {
|
||||
driveConfigService.updateCacheStatus(driveId, true);
|
||||
return ResultBean.success();
|
||||
}
|
||||
|
||||
@PostMapping("/{driveId}/disable")
|
||||
public ResultBean disableCache(@PathVariable("driveId") Integer driveId) {
|
||||
driveConfigService.updateCacheStatus(driveId, false);
|
||||
return ResultBean.success();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
package im.zhaojun.zfile.controller.admin;
|
||||
|
||||
import im.zhaojun.zfile.model.dto.DriveConfigDTO;
|
||||
import im.zhaojun.zfile.model.dto.ResultBean;
|
||||
import im.zhaojun.zfile.model.entity.DriveConfig;
|
||||
import im.zhaojun.zfile.service.DriveConfigService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 驱动器 Controller
|
||||
* @author zhaojun
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/admin")
|
||||
@Slf4j
|
||||
public class DriveController {
|
||||
|
||||
@Resource
|
||||
private DriveConfigService driveConfigService;
|
||||
|
||||
|
||||
/**
|
||||
* 获取所有驱动器列表
|
||||
*
|
||||
* @return 驱动器列表
|
||||
*/
|
||||
@GetMapping("drives")
|
||||
public ResultBean driveList() {
|
||||
List<DriveConfig> list = driveConfigService.list();
|
||||
return ResultBean.success(list);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取指定驱动器基本信息及其参数
|
||||
*
|
||||
* @param id
|
||||
* 驱动器 ID
|
||||
*
|
||||
* @return 驱动器基本信息信息
|
||||
*/
|
||||
@GetMapping("drive/{id}")
|
||||
public ResultBean driveItem(@PathVariable Integer id) {
|
||||
DriveConfigDTO driveConfig = driveConfigService.findDriveConfigDTOById(id);
|
||||
return ResultBean.success(driveConfig);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 保存驱动器设置
|
||||
*/
|
||||
@PostMapping("drive")
|
||||
public ResultBean saveDriveItem(@RequestBody DriveConfigDTO driveConfigDTO) {
|
||||
driveConfigService.save(driveConfigDTO);
|
||||
return ResultBean.success();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 删除驱动器设置
|
||||
*
|
||||
* @param id
|
||||
* 驱动器 ID
|
||||
*/
|
||||
@DeleteMapping("drive/{id}")
|
||||
public ResultBean deleteDriveItem(@PathVariable Integer id) {
|
||||
driveConfigService.deleteById(id);
|
||||
return ResultBean.success();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
package im.zhaojun.zfile.core;
|
||||
|
||||
import im.zhaojun.zfile.exception.StorageStrategyUninitializedException;
|
||||
import im.zhaojun.zfile.service.base.AbstractBaseFileService;
|
||||
import im.zhaojun.zfile.service.SystemConfigService;
|
||||
import im.zhaojun.zfile.util.SpringContextHolder;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.aspectj.lang.annotation.Before;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Aspect
|
||||
@Component
|
||||
public class StorageStrategyInitCheckAop {
|
||||
|
||||
@Before("@annotation(im.zhaojun.zfile.model.annotation.CheckStorageStrategyInit)")
|
||||
public void logStart() {
|
||||
SystemConfigService systemConfigService = SpringContextHolder.getBean(SystemConfigService.class);
|
||||
AbstractBaseFileService currentFileService = systemConfigService.getCurrentFileService();
|
||||
if (currentFileService == null) {
|
||||
throw new StorageStrategyUninitializedException("存储策略尚未初始化, 请联系管理员!");
|
||||
}
|
||||
if (currentFileService.getIsUnInitialized()) {
|
||||
throw new StorageStrategyUninitializedException("存储策略异常, 请联系管理员!");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -63,6 +63,30 @@ public class GlobleExceptionHandler {
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
* 文件预览异常
|
||||
*/
|
||||
@ExceptionHandler({PreviewException.class})
|
||||
@ResponseBody
|
||||
@ResponseStatus
|
||||
public ResultBean previewException(PreviewException ex) {
|
||||
return ResultBean.error(ex.getMessage());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 初始化异常
|
||||
*/
|
||||
@ExceptionHandler({InitializeException.class})
|
||||
@ResponseBody
|
||||
@ResponseStatus
|
||||
public ResultBean initializeException(InitializeException ex) {
|
||||
return ResultBean.error(ex.getMessage());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@ExceptionHandler
|
||||
@ResponseBody
|
||||
@ResponseStatus(code= HttpStatus.INTERNAL_SERVER_ERROR)
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
package im.zhaojun.zfile.exception;
|
||||
|
||||
/**
|
||||
* 文件预览异常类
|
||||
* @author zhaojun
|
||||
*/
|
||||
public class PreviewException extends RuntimeException {
|
||||
|
||||
public PreviewException() {
|
||||
}
|
||||
|
||||
public PreviewException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public PreviewException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public PreviewException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
public PreviewException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
|
||||
super(message, cause, enableSuppression, writableStackTrace);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package im.zhaojun.zfile.config;
|
||||
package im.zhaojun.zfile.filter;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.web.cors.CorsUtils;
|
||||
@@ -23,7 +23,6 @@ public class CorsFilter extends GenericFilterBean {
|
||||
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
|
||||
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
|
||||
|
||||
// Set customized header
|
||||
httpServletResponse.setHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, httpServletRequest.getHeader(HttpHeaders.ORIGIN));
|
||||
httpServletResponse.setHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS, "Origin, X-Requested-With, Content-Type, Accept");
|
||||
httpServletResponse.setHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS, "GET, POST, PUT, DELETE, OPTIONS");
|
||||
@@ -34,4 +33,5 @@ public class CorsFilter extends GenericFilterBean {
|
||||
chain.doFilter(httpServletRequest, httpServletResponse);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
package im.zhaojun.zfile.model.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* 标记注解, 用于在调用前检查是否已存储策略
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface CheckStorageStrategyInit {
|
||||
}
|
||||
@@ -5,7 +5,7 @@ package im.zhaojun.zfile.model.constant;
|
||||
*/
|
||||
public class StorageConfigConstant {
|
||||
|
||||
public static final String BUCKET_NAME_KEY = "bucket-name";
|
||||
public static final String BUCKET_NAME_KEY = "bucketName";
|
||||
|
||||
public static final String SECRET_ID_KEY = "secretId";
|
||||
|
||||
@@ -15,7 +15,7 @@ public class StorageConfigConstant {
|
||||
|
||||
public static final String ENDPOINT_KEY = "endPoint";
|
||||
|
||||
public static final String BASE_PATH = "base-path";
|
||||
public static final String BASE_PATH = "basePath";
|
||||
|
||||
public static final String DOMAIN_KEY = "domain";
|
||||
|
||||
|
||||
@@ -7,8 +7,6 @@ public class SystemConfigConstant {
|
||||
|
||||
public static final String SITE_NAME = "siteName";
|
||||
|
||||
public static final String INFO_ENABLE = "infoEnable";
|
||||
|
||||
public static final String SEARCH_ENABLE = "searchEnable";
|
||||
|
||||
public static final String SEARCH_IGNORE_CASE = "searchIgnoreCase";
|
||||
|
||||
@@ -28,6 +28,17 @@ public class ZFileConstant {
|
||||
*/
|
||||
public static String PASSWORD_FILE_NAME = "password.txt";
|
||||
|
||||
/**
|
||||
* 最大支持文件大小为 ? MB 的音乐文件解析封面, 歌手等信息.
|
||||
*/
|
||||
public static Long AUDIO_MAX_FILE_SIZE_MB = 1L;
|
||||
|
||||
/**
|
||||
* 最大支持文本文件大小为 ? KB 的文件内容.
|
||||
*/
|
||||
public static Long TEXT_MAX_FILE_SIZE_KB = 100L;
|
||||
|
||||
|
||||
@Autowired(required = false)
|
||||
public void setHeaderFileName(@Value("${zfile.constant.readme}") String headerFileName) {
|
||||
ZFileConstant.README_FILE_NAME = headerFileName;
|
||||
@@ -38,4 +49,15 @@ public class ZFileConstant {
|
||||
ZFileConstant.PASSWORD_FILE_NAME = passwordFileName;
|
||||
}
|
||||
|
||||
@Autowired(required = false)
|
||||
public void setAudioMaxFileSizeMb(@Value("${zfile.preview.audio.maxFileSizeMb}") Long maxFileSizeMb) {
|
||||
ZFileConstant.AUDIO_MAX_FILE_SIZE_MB = maxFileSizeMb;
|
||||
}
|
||||
|
||||
@Autowired(required = false)
|
||||
public void setTextMaxFileSizeMb(@Value("${zfile.preview.text.maxFileSizeKb}") Long maxFileSizeKb) {
|
||||
ZFileConstant.TEXT_MAX_FILE_SIZE_KB = maxFileSizeKb;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,53 +1,27 @@
|
||||
package im.zhaojun.zfile.model.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Data
|
||||
public class AudioInfoDTO {
|
||||
|
||||
private String title;
|
||||
|
||||
private String artist;
|
||||
|
||||
private String cover;
|
||||
|
||||
private String src;
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
public static AudioInfoDTO buildDefaultAudioInfoDTO() {
|
||||
AudioInfoDTO audioInfoDTO = new AudioInfoDTO();
|
||||
audioInfoDTO.setTitle("未知歌曲");
|
||||
audioInfoDTO.setArtist("未知");
|
||||
audioInfoDTO.setCover("http://c.jun6.net/audio.png");
|
||||
return audioInfoDTO;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public String getArtist() {
|
||||
return artist;
|
||||
}
|
||||
|
||||
public void setArtist(String artist) {
|
||||
this.artist = artist;
|
||||
}
|
||||
|
||||
public String getCover() {
|
||||
return cover;
|
||||
}
|
||||
|
||||
public void setCover(String cover) {
|
||||
this.cover = cover;
|
||||
}
|
||||
|
||||
public String getSrc() {
|
||||
return src;
|
||||
}
|
||||
|
||||
public void setSrc(String src) {
|
||||
this.src = src;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "AudioInfoDTO{" +
|
||||
"title='" + title + '\'' +
|
||||
", artist='" + artist + '\'' +
|
||||
", cover='" + cover + '\'' +
|
||||
", src='" + src + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
33
src/main/java/im/zhaojun/zfile/model/dto/DriveConfigDTO.java
Normal file
33
src/main/java/im/zhaojun/zfile/model/dto/DriveConfigDTO.java
Normal file
@@ -0,0 +1,33 @@
|
||||
package im.zhaojun.zfile.model.dto;
|
||||
|
||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||
import im.zhaojun.zfile.model.enums.StorageTypeEnum;
|
||||
import im.zhaojun.zfile.model.enums.StorageTypeEnumJsonDeSerializerConvert;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Data
|
||||
public class DriveConfigDTO {
|
||||
|
||||
private Integer id;
|
||||
|
||||
private String name;
|
||||
|
||||
@JsonDeserialize(using = StorageTypeEnumJsonDeSerializerConvert.class)
|
||||
private StorageTypeEnum type;
|
||||
|
||||
private boolean enableCache;
|
||||
|
||||
private boolean autoRefreshCache;
|
||||
|
||||
private boolean searchEnable;
|
||||
|
||||
private boolean searchIgnoreCase;
|
||||
|
||||
private boolean searchContainEncryptedFile;
|
||||
|
||||
private StorageStrategyConfig storageStrategyConfig;
|
||||
|
||||
}
|
||||
@@ -1,23 +1,23 @@
|
||||
package im.zhaojun.zfile.model.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Data
|
||||
@ToString
|
||||
public class SiteConfigDTO implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 8811196207046121740L;
|
||||
|
||||
private String readme;
|
||||
|
||||
@JsonProperty("viewConfig")
|
||||
private SystemConfigDTO systemConfigDTO;
|
||||
|
||||
}
|
||||
// package im.zhaojun.zfile.model.dto;
|
||||
//
|
||||
// import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
// import lombok.Data;
|
||||
// import lombok.ToString;
|
||||
//
|
||||
// import java.io.Serializable;
|
||||
//
|
||||
// /**
|
||||
// * @author zhaojun
|
||||
// */
|
||||
// @Data
|
||||
// @ToString
|
||||
// public class SiteConfigDTO implements Serializable {
|
||||
//
|
||||
// private static final long serialVersionUID = 8811196207046121740L;
|
||||
//
|
||||
// private String readme;
|
||||
//
|
||||
// @JsonProperty("viewConfig")
|
||||
// private SystemConfigDTO systemConfigDTO;
|
||||
//
|
||||
// }
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
package im.zhaojun.zfile.model.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Data
|
||||
public class StorageStrategyConfig {
|
||||
|
||||
private String endPoint;
|
||||
|
||||
private String pathStyle;
|
||||
|
||||
private Boolean isPrivate;
|
||||
|
||||
private String accessKey;
|
||||
|
||||
private String secretKey;
|
||||
|
||||
private String bucketName;
|
||||
|
||||
private String host;
|
||||
|
||||
private String port;
|
||||
|
||||
private String accessToken;
|
||||
|
||||
private String refreshToken;
|
||||
|
||||
private String secretId;
|
||||
|
||||
private String filePath;
|
||||
|
||||
private String username;
|
||||
|
||||
private String password;
|
||||
|
||||
private String domain;
|
||||
|
||||
private String basePath;
|
||||
|
||||
}
|
||||
@@ -9,6 +9,7 @@ import lombok.ToString;
|
||||
|
||||
/**
|
||||
* 系统设置传输类
|
||||
*
|
||||
* @author zhaojun
|
||||
*/
|
||||
@ToString
|
||||
@@ -20,26 +21,16 @@ public class SystemConfigDTO {
|
||||
|
||||
private String siteName;
|
||||
|
||||
private Boolean infoEnable;
|
||||
|
||||
private Boolean searchEnable;
|
||||
|
||||
private Boolean searchIgnoreCase;
|
||||
private String username;
|
||||
|
||||
@JsonSerialize(using = StorageTypeEnumSerializerConvert.class)
|
||||
private StorageTypeEnum storageStrategy;
|
||||
|
||||
private String username;
|
||||
|
||||
@JsonIgnore
|
||||
private String password;
|
||||
|
||||
private String domain;
|
||||
|
||||
private Boolean enableCache;
|
||||
|
||||
private Boolean searchContainEncryptedFile;
|
||||
|
||||
private String customJs;
|
||||
|
||||
private String customCss;
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
package im.zhaojun.zfile.model.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import lombok.Data;
|
||||
import lombok.ToString;
|
||||
|
||||
/**
|
||||
* 系统设置传输类
|
||||
* @author zhaojun
|
||||
*/
|
||||
@ToString
|
||||
@Data
|
||||
public class SystemFrontConfigDTO {
|
||||
|
||||
@JsonIgnore
|
||||
private Integer id;
|
||||
|
||||
private String siteName;
|
||||
|
||||
private Boolean searchEnable;
|
||||
|
||||
// @JsonSerialize(using = StorageTypeEnumSerializerConvert.class)
|
||||
// private StorageTypeEnum storageStrategy;
|
||||
|
||||
private String username;
|
||||
|
||||
private String domain;
|
||||
|
||||
private String customJs;
|
||||
|
||||
private String customCss;
|
||||
|
||||
private String tableSize;
|
||||
|
||||
private Boolean showOperator;
|
||||
|
||||
private Boolean showDocument;
|
||||
|
||||
private String announcement;
|
||||
|
||||
private Boolean showAnnouncement;
|
||||
|
||||
private String layout;
|
||||
|
||||
private String readme;
|
||||
|
||||
}
|
||||
38
src/main/java/im/zhaojun/zfile/model/entity/DriveConfig.java
Normal file
38
src/main/java/im/zhaojun/zfile/model/entity/DriveConfig.java
Normal file
@@ -0,0 +1,38 @@
|
||||
package im.zhaojun.zfile.model.entity;
|
||||
|
||||
import im.zhaojun.zfile.model.enums.StorageTypeEnum;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
|
||||
/**
|
||||
* 驱动器
|
||||
*
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Entity(name = "DRIVER_CONFIG")
|
||||
@Data
|
||||
public class DriveConfig {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Integer id;
|
||||
|
||||
private String name;
|
||||
|
||||
private Boolean enableCache;
|
||||
|
||||
private Boolean autoRefreshCache;
|
||||
|
||||
private StorageTypeEnum type;
|
||||
|
||||
private Boolean searchEnable;
|
||||
|
||||
private Boolean searchIgnoreCase;
|
||||
|
||||
private Boolean searchContainEncryptedFile;
|
||||
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Lob;
|
||||
|
||||
/**
|
||||
* @author zhaojun
|
||||
@@ -27,9 +28,16 @@ public class StorageConfig {
|
||||
|
||||
private String title;
|
||||
|
||||
@Column(length = 4000)
|
||||
@Lob
|
||||
private String value;
|
||||
|
||||
private Integer driveId;
|
||||
|
||||
public StorageConfig(String key, String title) {
|
||||
this.key = key;
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Lob;
|
||||
|
||||
/**
|
||||
* @author zhaojun
|
||||
@@ -22,6 +23,7 @@ public class SystemConfig {
|
||||
@Column(name = "k")
|
||||
private String key;
|
||||
|
||||
@Lob
|
||||
private String value;
|
||||
|
||||
private String remark;
|
||||
|
||||
@@ -12,4 +12,5 @@ public class StorageTypeEnumDeSerializerConvert implements Converter<String, Sto
|
||||
public StorageTypeEnum convert(@NonNull String s) {
|
||||
return StorageTypeEnum.getEnum(s);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package im.zhaojun.zfile.model.enums;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.databind.DeserializationContext;
|
||||
import com.fasterxml.jackson.databind.JsonDeserializer;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* @author zhaojun
|
||||
*/
|
||||
public class StorageTypeEnumJsonDeSerializerConvert extends JsonDeserializer<StorageTypeEnum> {
|
||||
|
||||
@Override
|
||||
public StorageTypeEnum deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
|
||||
return StorageTypeEnum.getEnum(jsonParser.getText());
|
||||
}
|
||||
}
|
||||
@@ -13,10 +13,8 @@ import java.util.List;
|
||||
@AllArgsConstructor
|
||||
public class FilePageModel {
|
||||
|
||||
private int total;
|
||||
|
||||
private int totalPage;
|
||||
|
||||
private List<FileItemDTO> fileList;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,5 @@
|
||||
package im.zhaojun.zfile.model.support;
|
||||
|
||||
import im.zhaojun.zfile.model.support.Jvm;
|
||||
import im.zhaojun.zfile.model.support.Mem;
|
||||
import im.zhaojun.zfile.model.support.Sys;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
package im.zhaojun.zfile.repository;
|
||||
|
||||
import im.zhaojun.zfile.model.entity.DriveConfig;
|
||||
import im.zhaojun.zfile.model.enums.StorageTypeEnum;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Repository
|
||||
public interface DriverConfigRepository extends JpaRepository<DriveConfig, Integer> {
|
||||
|
||||
/**
|
||||
* 根据存储策略类型获取所有驱动器
|
||||
*
|
||||
* @param type
|
||||
* 存储类型
|
||||
*
|
||||
* @return 指定存储类型的存储器
|
||||
*/
|
||||
List<DriveConfig> findByType(StorageTypeEnum type);
|
||||
|
||||
}
|
||||
@@ -15,17 +15,57 @@ public interface StorageConfigRepository extends JpaRepository<StorageConfig, In
|
||||
|
||||
/**
|
||||
* 根据存储类型找对应的配置信息
|
||||
* @param type 存储类型
|
||||
* @return 此类型所有的配置信息
|
||||
*
|
||||
* @param type
|
||||
* 存储类型
|
||||
*
|
||||
* @return 此类型所有的配置信息
|
||||
*/
|
||||
List<StorageConfig> findByTypeOrderById(StorageTypeEnum type);
|
||||
|
||||
|
||||
/**
|
||||
* 根据存储类型找到某个 KEY 的值
|
||||
* @param type 存储类型
|
||||
* @param key KEY
|
||||
* @return KEY 对应的对象
|
||||
* 根据存储类型找对应的配置信息
|
||||
*
|
||||
* @param driveId
|
||||
* 驱动器 ID
|
||||
*
|
||||
* @return 此驱动器所有的配置信息
|
||||
*/
|
||||
StorageConfig findByTypeAndKey(StorageTypeEnum type, String key);
|
||||
List<StorageConfig> findByDriveIdOrderById(Integer driveId);
|
||||
|
||||
|
||||
/**
|
||||
* 根据驱动器找到对应的配置信息
|
||||
*
|
||||
* @param driveId
|
||||
* 驱动器 ID
|
||||
*
|
||||
* @return 此驱动器所有的配置信息
|
||||
*/
|
||||
List<StorageConfig> findByDriveId(Integer driveId);
|
||||
|
||||
|
||||
/**
|
||||
* 删除指定驱动器对应的配置信息
|
||||
*
|
||||
* @param driveId
|
||||
* 驱动器 ID
|
||||
*/
|
||||
void deleteByDriveId(Integer driveId);
|
||||
|
||||
|
||||
/**
|
||||
* 查找某个驱动器的某个 KEY 的值
|
||||
*
|
||||
* @param driveId
|
||||
* 驱动器
|
||||
*
|
||||
* @param key
|
||||
* KEY 值
|
||||
*
|
||||
* @return KEY 对应的对象
|
||||
*/
|
||||
StorageConfig findByDriveIdAndKey(Integer driveId, String key);
|
||||
|
||||
}
|
||||
@@ -12,8 +12,12 @@ public interface SystemConfigRepository extends JpaRepository<SystemConfig, Inte
|
||||
|
||||
/**
|
||||
* 查找系统设置中, 某个设置项对应的值
|
||||
* @param key 设置项
|
||||
* @return 设置值
|
||||
*
|
||||
* @param key
|
||||
* 设置项
|
||||
*
|
||||
* @return 设置值
|
||||
*/
|
||||
SystemConfig findByKey(String key);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package im.zhaojun.zfile.schedule;
|
||||
|
||||
import im.zhaojun.zfile.model.entity.DriveConfig;
|
||||
import im.zhaojun.zfile.model.enums.StorageTypeEnum;
|
||||
import im.zhaojun.zfile.service.DriveConfigService;
|
||||
import im.zhaojun.zfile.service.base.AbstractOneDriveServiceBase;
|
||||
import im.zhaojun.zfile.service.impl.OneDriveChinaServiceImpl;
|
||||
import im.zhaojun.zfile.service.impl.OneDriveServiceImpl;
|
||||
import im.zhaojun.zfile.context.DriveContext;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 计划任务工具类
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Configuration
|
||||
@EnableScheduling
|
||||
@Slf4j
|
||||
public class GlobalScheduleTask {
|
||||
|
||||
@Resource
|
||||
private OneDriveServiceImpl oneDriveServiceImpl;
|
||||
|
||||
@Resource
|
||||
private OneDriveChinaServiceImpl oneDriveChinaServiceImpl;
|
||||
|
||||
@Resource
|
||||
private DriveConfigService driveConfigService;
|
||||
|
||||
@Resource
|
||||
private DriveContext driveContext;
|
||||
|
||||
/**
|
||||
* 项目启动 30 秒后, 每 15 分钟执行一次刷新 OneDrive Token 的定时任务.
|
||||
*/
|
||||
@Scheduled(fixedRate = 1000 * 60 * 10, initialDelay = 1000 * 30)
|
||||
public void autoRefreshOneDriveToken() {
|
||||
|
||||
try {
|
||||
log.debug("尝试调用 OneDrive 自动刷新 AccessToken 定时任务");
|
||||
|
||||
List<DriveConfig> driveConfigList = driveConfigService.findByType(StorageTypeEnum.ONE_DRIVE);
|
||||
driveConfigList.addAll(driveConfigService.findByType(StorageTypeEnum.ONE_DRIVE_CHINA));
|
||||
|
||||
driveConfigList.forEach(driveConfig -> {
|
||||
StorageTypeEnum storageType = driveConfig.getType();
|
||||
String name = driveConfig.getName();
|
||||
|
||||
try {
|
||||
AbstractOneDriveServiceBase driveService = (AbstractOneDriveServiceBase) driveContext.getDriveService(driveConfig.getId());
|
||||
driveService.refreshOneDriveToken();
|
||||
log.info("刷新驱动器 {}, {} key 时间: {}", name, storageType.getDescription(), LocalDateTime.now());
|
||||
} catch (Exception e) {
|
||||
log.debug("刷新驱动器 " + name + " Token 失败.", e);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
} catch (Throwable e) {
|
||||
log.debug("尝试调用 OneDrive 自动刷新 AccessToken 定时任务出现未知异常", e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -30,4 +30,5 @@ public class MyUserDetailsServiceImpl implements UserDetailsService {
|
||||
}
|
||||
return new User(systemConfig.getUsername(), systemConfig.getPassword(), Collections.emptyList());
|
||||
}
|
||||
|
||||
}
|
||||
224
src/main/java/im/zhaojun/zfile/service/DriveConfigService.java
Normal file
224
src/main/java/im/zhaojun/zfile/service/DriveConfigService.java
Normal file
@@ -0,0 +1,224 @@
|
||||
package im.zhaojun.zfile.service;
|
||||
|
||||
import im.zhaojun.zfile.context.StorageTypeContext;
|
||||
import im.zhaojun.zfile.exception.InitializeException;
|
||||
import im.zhaojun.zfile.model.constant.StorageConfigConstant;
|
||||
import im.zhaojun.zfile.model.dto.DriveConfigDTO;
|
||||
import im.zhaojun.zfile.model.dto.StorageStrategyConfig;
|
||||
import im.zhaojun.zfile.model.entity.DriveConfig;
|
||||
import im.zhaojun.zfile.model.entity.StorageConfig;
|
||||
import im.zhaojun.zfile.model.enums.StorageTypeEnum;
|
||||
import im.zhaojun.zfile.repository.DriverConfigRepository;
|
||||
import im.zhaojun.zfile.repository.StorageConfigRepository;
|
||||
import im.zhaojun.zfile.service.base.AbstractBaseFileService;
|
||||
import im.zhaojun.zfile.context.DriveContext;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 驱动器 Service 类
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class DriveConfigService {
|
||||
|
||||
@Resource
|
||||
private DriverConfigRepository driverConfigRepository;
|
||||
|
||||
@Resource
|
||||
private StorageConfigRepository storageConfigRepository;
|
||||
|
||||
@Resource
|
||||
private DriveContext driveContext;
|
||||
|
||||
public static final Class<StorageStrategyConfig> STORAGE_STRATEGY_CONFIG_CLASS = StorageStrategyConfig.class;
|
||||
|
||||
/**
|
||||
* 获取所有驱动器列表
|
||||
*
|
||||
* @return 驱动器列表
|
||||
*/
|
||||
public List<DriveConfig> list() {
|
||||
return driverConfigRepository.findAll();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取指定驱动器设置
|
||||
*
|
||||
* @param id
|
||||
* 驱动器 ID
|
||||
*
|
||||
* @return 驱动器设置
|
||||
*/
|
||||
public DriveConfig findById(Integer id) {
|
||||
return driverConfigRepository.getOne(id);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取指定驱动器 DTO 对象, 此对象包含详细的参数设置.
|
||||
*
|
||||
* @param id
|
||||
* 驱动器 ID
|
||||
*
|
||||
* @return 驱动器 DTO
|
||||
*/
|
||||
public DriveConfigDTO findDriveConfigDTOById(Integer id) {
|
||||
DriveConfig driveConfig = driverConfigRepository.getOne(id);
|
||||
|
||||
DriveConfigDTO driveConfigDTO = new DriveConfigDTO();
|
||||
|
||||
List<StorageConfig> storageConfigList = storageConfigRepository.findByDriveId(driveConfig.getId());
|
||||
BeanUtils.copyProperties(driveConfig, driveConfigDTO);
|
||||
|
||||
StorageStrategyConfig storageStrategyConfig = new StorageStrategyConfig();
|
||||
for (StorageConfig storageConfig : storageConfigList) {
|
||||
String key = storageConfig.getKey();
|
||||
String value = storageConfig.getValue();
|
||||
|
||||
Field declaredField;
|
||||
try {
|
||||
declaredField = STORAGE_STRATEGY_CONFIG_CLASS.getDeclaredField(key);
|
||||
declaredField.setAccessible(true);
|
||||
if (Objects.equals(StorageConfigConstant.IS_PRIVATE, key)) {
|
||||
declaredField.set(storageStrategyConfig, Boolean.valueOf(value));
|
||||
} else {
|
||||
declaredField.set(storageStrategyConfig, value);
|
||||
}
|
||||
} catch (NoSuchFieldException | IllegalAccessException e) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("通过反射, 将字段 {" + key + "}注入 DriveConfigDTO 时出现异常:", e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
driveConfigDTO.setStorageStrategyConfig(storageStrategyConfig);
|
||||
return driveConfigDTO;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定驱动器的存储策略.
|
||||
*
|
||||
* @param id
|
||||
* 驱动器 ID
|
||||
*
|
||||
* @return 驱动器对应的存储策略.
|
||||
*/
|
||||
public StorageTypeEnum findStorageTypeById(Integer id) {
|
||||
// return findById(id).getType();
|
||||
return driverConfigRepository.findById(id).get().getType();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 保存驱动器基本信息及其对应的参数设置
|
||||
*
|
||||
* @param driveConfigDTO 驱动器 DTO 对象
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void save(DriveConfigDTO driveConfigDTO) {
|
||||
|
||||
// 判断是新增还是修改
|
||||
boolean updateFlag = driveConfigDTO.getId() != null;
|
||||
|
||||
// 保存基本信息
|
||||
DriveConfig driveConfig = new DriveConfig();
|
||||
StorageTypeEnum storageType = driveConfigDTO.getType();
|
||||
BeanUtils.copyProperties(driveConfigDTO, driveConfig);
|
||||
driverConfigRepository.save(driveConfig);
|
||||
|
||||
// 保存存储策略设置.
|
||||
StorageStrategyConfig storageStrategyConfig = driveConfigDTO.getStorageStrategyConfig();
|
||||
|
||||
AbstractBaseFileService storageTypeService = StorageTypeContext.getStorageTypeService(storageType);
|
||||
|
||||
List<StorageConfig> storageConfigList;
|
||||
if (updateFlag) {
|
||||
storageConfigList = storageConfigRepository.findByDriveId(driveConfigDTO.getId());
|
||||
} else {
|
||||
storageConfigList = storageTypeService.storageStrategyConfigList();
|
||||
}
|
||||
|
||||
for (StorageConfig storageConfig : storageConfigList) {
|
||||
String key = storageConfig.getKey();
|
||||
|
||||
try {
|
||||
Field field = STORAGE_STRATEGY_CONFIG_CLASS.getDeclaredField(key);
|
||||
field.setAccessible(true);
|
||||
Object o = field.get(storageStrategyConfig);
|
||||
String value = o == null ? null : o.toString();
|
||||
storageConfig.setValue(value);
|
||||
storageConfig.setType(storageType);
|
||||
storageConfig.setDriveId(driveConfig.getId());
|
||||
} catch (IllegalAccessException | NoSuchFieldException e) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("通过反射, 从 StorageStrategyConfig 中获取字段 {" + key + "} 时出现异常:", e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
storageConfigRepository.saveAll(storageConfigList);
|
||||
|
||||
driveContext.initDrive(driveConfig.getId());
|
||||
|
||||
AbstractBaseFileService driveService = driveContext.getDriveService(driveConfig.getId());
|
||||
if (driveService.getIsUnInitialized()) {
|
||||
throw new InitializeException("初始化异常, 请检查配置是否正确.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 删除指定驱动器设置, 会级联删除其参数设置
|
||||
*
|
||||
* @param id
|
||||
* 驱动器 ID
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void deleteById(Integer id) {
|
||||
driverConfigRepository.deleteById(id);
|
||||
storageConfigRepository.deleteByDriveId(id);
|
||||
driveContext.destroyDrive(id);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据存储策略类型获取所有驱动器
|
||||
*
|
||||
* @param type
|
||||
* 存储类型
|
||||
*
|
||||
* @return 指定存储类型的存储器
|
||||
*/
|
||||
public List<DriveConfig> findByType(StorageTypeEnum type) {
|
||||
return driverConfigRepository.findByType(type);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 更新指定驱动器的缓存启用状态
|
||||
*
|
||||
* @param driveId
|
||||
* 驱动器 ID
|
||||
*
|
||||
* @param cacheEnable
|
||||
* 是否启用缓存
|
||||
*/
|
||||
public void updateCacheStatus(Integer driveId, Boolean cacheEnable) {
|
||||
DriveConfig driveConfig = findById(driveId);
|
||||
if (driveConfig != null) {
|
||||
driveConfig.setEnableCache(cacheEnable);
|
||||
driverConfigRepository.save(driveConfig);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,13 +19,19 @@ public class StorageConfigService {
|
||||
@Resource
|
||||
private StorageConfigRepository storageConfigRepository;
|
||||
|
||||
|
||||
public List<StorageConfig> selectStorageConfigByType(StorageTypeEnum storageTypeEnum) {
|
||||
return storageConfigRepository.findByTypeOrderById(storageTypeEnum);
|
||||
}
|
||||
|
||||
|
||||
public StorageConfig selectByTypeAndKey(StorageTypeEnum storageType, String key) {
|
||||
return storageConfigRepository.findByTypeAndKey(storageType, key);
|
||||
public List<StorageConfig> selectStorageConfigByDriveId(Integer driveId) {
|
||||
return storageConfigRepository.findByDriveIdOrderById(driveId);
|
||||
}
|
||||
|
||||
|
||||
public StorageConfig findByDriveIdAndKey(Integer driveId, String key) {
|
||||
return storageConfigRepository.findByDriveIdAndKey(driveId, key);
|
||||
}
|
||||
|
||||
|
||||
@@ -38,8 +44,17 @@ public class StorageConfigService {
|
||||
}
|
||||
|
||||
|
||||
public Map<String, StorageConfig> selectStorageConfigMapByDriveId(Integer driveId) {
|
||||
Map<String, StorageConfig> map = new HashMap<>(24);
|
||||
for (StorageConfig storageConfig : selectStorageConfigByDriveId(driveId)) {
|
||||
map.put(storageConfig.getKey(), storageConfig);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
|
||||
public void updateStorageConfig(List<StorageConfig> storageConfigList) {
|
||||
storageConfigRepository.saveAll(storageConfigList);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,17 +1,16 @@
|
||||
package im.zhaojun.zfile.service;
|
||||
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.util.BooleanUtil;
|
||||
import cn.hutool.crypto.SecureUtil;
|
||||
import im.zhaojun.zfile.cache.ZFileCache;
|
||||
import im.zhaojun.zfile.config.StorageTypeFactory;
|
||||
import im.zhaojun.zfile.model.constant.SystemConfigConstant;
|
||||
import im.zhaojun.zfile.model.dto.SystemConfigDTO;
|
||||
import im.zhaojun.zfile.model.dto.SystemFrontConfigDTO;
|
||||
import im.zhaojun.zfile.model.entity.DriveConfig;
|
||||
import im.zhaojun.zfile.model.entity.SystemConfig;
|
||||
import im.zhaojun.zfile.model.enums.StorageTypeEnum;
|
||||
import im.zhaojun.zfile.repository.SystemConfigRepository;
|
||||
import im.zhaojun.zfile.service.base.AbstractBaseFileService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
@@ -32,8 +31,17 @@ public class SystemConfigService {
|
||||
@Resource
|
||||
private SystemConfigRepository systemConfigRepository;
|
||||
|
||||
@Resource
|
||||
private DriveConfigService driveConfigService;
|
||||
|
||||
private Class<SystemConfigDTO> systemConfigClazz = SystemConfigDTO.class;
|
||||
|
||||
|
||||
/**
|
||||
* 获取系统设置, 如果缓存中有, 则去缓存取, 没有则查询数据库并写入到缓存中.
|
||||
*
|
||||
* @return 系统设置
|
||||
*/
|
||||
public SystemConfigDTO getSystemConfig() {
|
||||
SystemConfigDTO cacheConfig = zFileCache.getConfig();
|
||||
if (cacheConfig != null) {
|
||||
@@ -48,12 +56,10 @@ public class SystemConfigService {
|
||||
|
||||
try {
|
||||
Field field = systemConfigClazz.getDeclaredField(key);
|
||||
if (field != null) {
|
||||
field.setAccessible(true);
|
||||
String strVal = systemConfig.getValue();
|
||||
Object convertVal = Convert.convert(field.getType(), strVal);
|
||||
field.set(systemConfigDTO, convertVal);
|
||||
}
|
||||
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);
|
||||
@@ -66,7 +72,14 @@ public class SystemConfigService {
|
||||
}
|
||||
|
||||
|
||||
public void updateSystemConfig(SystemConfigDTO systemConfigDTO) throws Exception {
|
||||
/**
|
||||
* 更新系统设置, 并清空缓存中的内容.
|
||||
*
|
||||
* @param systemConfigDTO
|
||||
* 系统
|
||||
*
|
||||
*/
|
||||
public void updateSystemConfig(SystemConfigDTO systemConfigDTO) {
|
||||
List<SystemConfig> systemConfigList = new ArrayList<>();
|
||||
|
||||
Field[] fields = systemConfigClazz.getDeclaredFields();
|
||||
@@ -75,7 +88,16 @@ public class SystemConfigService {
|
||||
SystemConfig systemConfig = systemConfigRepository.findByKey(key);
|
||||
if (systemConfig != null) {
|
||||
field.setAccessible(true);
|
||||
Object val = field.get(systemConfigDTO);
|
||||
Object val = null;
|
||||
|
||||
try {
|
||||
val = field.get(systemConfigDTO);
|
||||
} catch (IllegalAccessException e) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("通过反射, 从 SystemConfigDTO 获取字段 {" + key + "} 时出现异常:", e);
|
||||
}
|
||||
}
|
||||
|
||||
if (val != null) {
|
||||
systemConfig.setValue(val.toString());
|
||||
systemConfigList.add(systemConfig);
|
||||
@@ -88,6 +110,34 @@ public class SystemConfigService {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据驱动器 ID, 获取对于前台页面的系统设置.
|
||||
*
|
||||
* @param driveId
|
||||
* 驱动器 ID
|
||||
*
|
||||
* @return 前台系统设置
|
||||
*/
|
||||
public SystemFrontConfigDTO getSystemFrontConfig(Integer driveId) {
|
||||
SystemConfigDTO systemConfig = getSystemConfig();
|
||||
SystemFrontConfigDTO systemFrontConfigDTO = new SystemFrontConfigDTO();
|
||||
BeanUtils.copyProperties(systemConfig, systemFrontConfigDTO);
|
||||
|
||||
DriveConfig driveConfig = driveConfigService.findById(driveId);
|
||||
systemFrontConfigDTO.setSearchEnable(driveConfig.getSearchEnable());
|
||||
return systemFrontConfigDTO;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 更新后台账号密码
|
||||
*
|
||||
* @param username
|
||||
* 用户名
|
||||
*
|
||||
* @param password
|
||||
* 密码
|
||||
*/
|
||||
public void updateUsernameAndPwd(String username, String password) {
|
||||
SystemConfig usernameConfig = systemConfigRepository.findByKey(SystemConfigConstant.USERNAME);
|
||||
usernameConfig.setValue(username);
|
||||
@@ -103,34 +153,14 @@ public class SystemConfigService {
|
||||
}
|
||||
|
||||
|
||||
public void updateCacheEnableConfig(Boolean isEnable) {
|
||||
SystemConfig enableConfig = systemConfigRepository.findByKey(SystemConfigConstant.ENABLE_CACHE);
|
||||
enableConfig.setValue(isEnable.toString());
|
||||
systemConfigRepository.save(enableConfig);
|
||||
zFileCache.removeConfig();
|
||||
}
|
||||
|
||||
|
||||
public AbstractBaseFileService getCurrentFileService() {
|
||||
StorageTypeEnum storageStrategy = getCurrentStorageStrategy();
|
||||
return StorageTypeFactory.getStorageTypeService(storageStrategy);
|
||||
}
|
||||
|
||||
|
||||
public StorageTypeEnum getCurrentStorageStrategy() {
|
||||
/**
|
||||
* 获取管理员名称
|
||||
*
|
||||
* @return 管理员名称
|
||||
*/
|
||||
public String getAdminUsername() {
|
||||
SystemConfigDTO systemConfigDTO = getSystemConfig();
|
||||
return systemConfigDTO.getStorageStrategy();
|
||||
return systemConfigDTO.getUsername();
|
||||
}
|
||||
|
||||
public boolean getEnableCache() {
|
||||
SystemConfigDTO systemConfigDTO = getSystemConfig();
|
||||
return BooleanUtil.isTrue(systemConfigDTO.getEnableCache());
|
||||
}
|
||||
|
||||
public boolean getSearchIgnoreCase() {
|
||||
SystemConfigDTO systemConfigDTO = getSystemConfig();
|
||||
return BooleanUtil.isTrue(systemConfigDTO.getSearchIgnoreCase());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,67 +1,69 @@
|
||||
package im.zhaojun.zfile.service;
|
||||
|
||||
import im.zhaojun.zfile.model.constant.ZFileConstant;
|
||||
import im.zhaojun.zfile.model.dto.FileItemDTO;
|
||||
import im.zhaojun.zfile.model.dto.SiteConfigDTO;
|
||||
import im.zhaojun.zfile.model.enums.StorageTypeEnum;
|
||||
import im.zhaojun.zfile.service.base.AbstractBaseFileService;
|
||||
import im.zhaojun.zfile.util.HttpUtil;
|
||||
import im.zhaojun.zfile.util.StringUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.client.HttpClientErrorException;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class SystemService {
|
||||
|
||||
@Resource
|
||||
private SystemConfigService systemConfigService;
|
||||
|
||||
/**
|
||||
* 构建指定路径下标题, 页面文档信息
|
||||
* @param path 路径
|
||||
*/
|
||||
public SiteConfigDTO getConfig(String path) throws Exception {
|
||||
|
||||
SiteConfigDTO siteConfigDTO = new SiteConfigDTO();
|
||||
AbstractBaseFileService fileService = systemConfigService.getCurrentFileService();
|
||||
|
||||
List<FileItemDTO> fileItemList;
|
||||
|
||||
if (Objects.equals(systemConfigService.getSystemConfig().getStorageStrategy(), StorageTypeEnum.FTP)) {
|
||||
fileItemList = new ArrayList<>();
|
||||
} else {
|
||||
fileItemList = fileService.fileList(path);
|
||||
}
|
||||
|
||||
for (FileItemDTO fileItemDTO : fileItemList) {
|
||||
if (ZFileConstant.README_FILE_NAME.equalsIgnoreCase(fileItemDTO.getName())) {
|
||||
String textContent = null;
|
||||
try {
|
||||
textContent = HttpUtil.getTextContent(fileItemDTO.getUrl());
|
||||
} catch (HttpClientErrorException httpClientErrorException) {
|
||||
log.debug("尝试重新获取文档区缓存中链接后仍失败", httpClientErrorException);
|
||||
try {
|
||||
String fullPath = StringUtils.removeDuplicateSeparator(fileItemDTO.getPath() + "/" + fileItemDTO.getName());
|
||||
FileItemDTO fileItem = fileService.getFileItem(fullPath);
|
||||
textContent = HttpUtil.getTextContent(fileItem.getUrl());
|
||||
} catch (Exception e) {
|
||||
log.debug("尝试重新获取文档区链接后仍失败, 已置为空", e);
|
||||
}
|
||||
}
|
||||
siteConfigDTO.setReadme(textContent);
|
||||
}
|
||||
}
|
||||
return siteConfigDTO;
|
||||
}
|
||||
|
||||
}
|
||||
// package im.zhaojun.zfile.service;
|
||||
//
|
||||
// import im.zhaojun.zfile.model.constant.ZFileConstant;
|
||||
// import im.zhaojun.zfile.model.dto.FileItemDTO;
|
||||
// import im.zhaojun.zfile.model.dto.SiteConfigDTO;
|
||||
// import im.zhaojun.zfile.model.enums.StorageTypeEnum;
|
||||
// import im.zhaojun.zfile.service.base.AbstractBaseFileService;
|
||||
// import im.zhaojun.zfile.context.DriveContext;
|
||||
// import im.zhaojun.zfile.util.HttpUtil;
|
||||
// import im.zhaojun.zfile.util.StringUtils;
|
||||
// import lombok.extern.slf4j.Slf4j;
|
||||
// import org.springframework.stereotype.Service;
|
||||
// import org.springframework.web.client.HttpClientErrorException;
|
||||
//
|
||||
// import javax.annotation.Resource;
|
||||
// import java.util.ArrayList;
|
||||
// import java.util.List;
|
||||
// import java.util.Objects;
|
||||
//
|
||||
// /**
|
||||
// * @author zhaojun
|
||||
// */
|
||||
// @Slf4j
|
||||
// @Service
|
||||
// public class SystemService {
|
||||
//
|
||||
// @Resource
|
||||
// private DriveContext driveContext;
|
||||
//
|
||||
// /**
|
||||
// * 构建指定路径下标题, 页面文档信息
|
||||
// * @param path 路径
|
||||
// */
|
||||
// public SiteConfigDTO getConfig(Integer driveId, String path) throws Exception {
|
||||
//
|
||||
// SiteConfigDTO siteConfigDTO = new SiteConfigDTO();
|
||||
//
|
||||
// AbstractBaseFileService fileService = driveContext.getDriveService(driveId);
|
||||
//
|
||||
// List<FileItemDTO> fileItemList;
|
||||
//
|
||||
// if (Objects.equals(fileService.getStorageTypeEnum(), StorageTypeEnum.FTP)) {
|
||||
// fileItemList = new ArrayList<>();
|
||||
// } else {
|
||||
// fileItemList = fileService.fileList(path);
|
||||
// }
|
||||
//
|
||||
// for (FileItemDTO fileItemDTO : fileItemList) {
|
||||
// if (ZFileConstant.README_FILE_NAME.equalsIgnoreCase(fileItemDTO.getName())) {
|
||||
// String textContent = null;
|
||||
// try {
|
||||
// textContent = HttpUtil.getTextContent(fileItemDTO.getUrl());
|
||||
// } catch (HttpClientErrorException httpClientErrorException) {
|
||||
// log.debug("尝试重新获取文档区缓存中链接后仍失败", httpClientErrorException);
|
||||
// try {
|
||||
// String fullPath = StringUtils.removeDuplicateSeparator(fileItemDTO.getPath() + "/" + fileItemDTO.getName());
|
||||
// FileItemDTO fileItem = fileService.getFileItem(fullPath);
|
||||
// textContent = HttpUtil.getTextContent(fileItem.getUrl());
|
||||
// } catch (Exception e) {
|
||||
// log.debug("尝试重新获取文档区链接后仍失败, 已置为空", e);
|
||||
// }
|
||||
// }
|
||||
// siteConfigDTO.setReadme(textContent);
|
||||
// }
|
||||
// }
|
||||
// return siteConfigDTO;
|
||||
// }
|
||||
//
|
||||
// }
|
||||
|
||||
@@ -1,18 +1,14 @@
|
||||
package im.zhaojun.zfile.service.base;
|
||||
|
||||
import cn.hutool.core.util.BooleanUtil;
|
||||
import im.zhaojun.zfile.cache.ZFileCache;
|
||||
import im.zhaojun.zfile.model.dto.FileItemDTO;
|
||||
import im.zhaojun.zfile.model.dto.SystemConfigDTO;
|
||||
import im.zhaojun.zfile.model.entity.StorageConfig;
|
||||
import im.zhaojun.zfile.model.enums.StorageTypeEnum;
|
||||
import im.zhaojun.zfile.service.SystemConfigService;
|
||||
import im.zhaojun.zfile.service.support.FileAsyncCacheService;
|
||||
import im.zhaojun.zfile.service.support.FileCacheService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.aop.framework.AopContext;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
@@ -20,49 +16,69 @@ import java.util.List;
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Slf4j
|
||||
public abstract class AbstractBaseFileService extends FileCacheService implements BaseFileService {
|
||||
public abstract class AbstractBaseFileService implements BaseFileService {
|
||||
|
||||
/**
|
||||
* 下载链接过期时间, 目前只在兼容 S3 协议的存储策略中使用到.
|
||||
*/
|
||||
@Value("${zfile.cache.timeout}")
|
||||
protected Long timeout;
|
||||
|
||||
/**
|
||||
* 是否初始化成功
|
||||
*/
|
||||
protected boolean isInitialized = false;
|
||||
|
||||
|
||||
/**
|
||||
* 基路径
|
||||
*/
|
||||
protected String basePath;
|
||||
/**
|
||||
* 驱动器 ID
|
||||
*/
|
||||
public Integer driveId;
|
||||
|
||||
@Resource
|
||||
private SystemConfigService systemConfigService;
|
||||
|
||||
@Resource
|
||||
private FileAsyncCacheService fileAsyncCacheService;
|
||||
|
||||
@Resource
|
||||
private ZFileCache zFileCache;
|
||||
|
||||
|
||||
/***
|
||||
* 获取指定路径下的文件及文件夹, 默认缓存 60 分钟,每隔 30 分钟刷新一次.
|
||||
* @param path 文件路径
|
||||
* @return 文件及文件夹列表
|
||||
*
|
||||
* @param path
|
||||
* 文件路径
|
||||
*
|
||||
* @return 文件及文件夹列表
|
||||
*
|
||||
* @throws Exception 获取文件列表中出现的异常
|
||||
*/
|
||||
@Override
|
||||
public abstract List<FileItemDTO> fileList(String path) throws Exception;
|
||||
|
||||
|
||||
/**
|
||||
* 清理当前存储策略的缓存
|
||||
* 1. 删除全部缓存
|
||||
* 2. 标记为当前处于未完成缓存状态
|
||||
*/
|
||||
public void clearFileCache() {
|
||||
zFileCache.clear();
|
||||
fileAsyncCacheService.setCacheFinish(false);
|
||||
zFileCache.clear(driveId);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 初始化方法, 启动时自动调用实现类的此方法进行初始化.
|
||||
*/
|
||||
@PostConstruct
|
||||
public abstract void init();
|
||||
public abstract void init(Integer driveId);
|
||||
|
||||
|
||||
/**
|
||||
* 测试是否连接成功, 会尝试取调用获取根路径的文件, 如果没有抛出异常, 则认为连接成功, 某些存储策略需要复写此方法.
|
||||
*
|
||||
* @return 连接结果
|
||||
*/
|
||||
protected boolean testConnection() {
|
||||
boolean flag = true;
|
||||
try {
|
||||
@@ -74,55 +90,79 @@ public abstract class AbstractBaseFileService extends FileCacheService implement
|
||||
return flag;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取是否初始化成功
|
||||
* @return 初始化成功与否
|
||||
*
|
||||
* @return 初始化成功与否
|
||||
*/
|
||||
public boolean getIsUnInitialized() {
|
||||
return !isInitialized;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取是否初始化成功
|
||||
* @return 初始化成功与否
|
||||
*
|
||||
* @return 初始化成功与否
|
||||
*/
|
||||
public boolean getIsInitialized() {
|
||||
return isInitialized;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取存储策略类型
|
||||
* @return 存储策略类型枚举
|
||||
* 获取当前实现类的存储策略类型
|
||||
*
|
||||
* @return 存储策略类型枚举对象
|
||||
*/
|
||||
public abstract StorageTypeEnum getStorageTypeEnum();
|
||||
|
||||
|
||||
/**
|
||||
* 获取初始化当前存储策略, 所需要的参数信息 (表单填写)
|
||||
*
|
||||
* @return 初始化所需的参数列表
|
||||
*/
|
||||
public abstract List<StorageConfig> storageStrategyConfigList();
|
||||
|
||||
|
||||
/**
|
||||
* 搜索文件
|
||||
* @param name 文件名
|
||||
* @return 包含该文件名的所有文件或文件夹
|
||||
*
|
||||
* @param name
|
||||
* 文件名
|
||||
*
|
||||
* @return 包含该文件名的所有文件或文件夹
|
||||
*/
|
||||
public List<FileItemDTO> search(String name) {
|
||||
SystemConfigDTO systemConfig = systemConfigService.getSystemConfig();
|
||||
|
||||
boolean searchIgnoreCase = BooleanUtil.isTrue(systemConfig.getSearchIgnoreCase());
|
||||
boolean searchContainEncryptedFile = BooleanUtil.isTrue(systemConfig.getSearchContainEncryptedFile());
|
||||
return zFileCache.find(name, searchIgnoreCase, searchContainEncryptedFile);
|
||||
return zFileCache.find(driveId, name);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 刷新缓存
|
||||
* 刷新指定 key 的缓存:
|
||||
* 1. 清空此 key 的缓存.
|
||||
* 2. 重新调用方法写入缓存.
|
||||
*
|
||||
* @param key
|
||||
* 缓存 key (文件夹名称)
|
||||
*/
|
||||
public void refreshCache(String key) throws Exception {
|
||||
zFileCache.remove(key);
|
||||
zFileCache.remove(driveId, key);
|
||||
BaseFileService currentFileService = (BaseFileService) AopContext.currentProxy();
|
||||
currentFileService.fileList(key);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取单个文件信息
|
||||
* @param path 文件路径
|
||||
*
|
||||
* @param path
|
||||
* 文件路径
|
||||
*
|
||||
* @return 单个文件的内容.
|
||||
*/
|
||||
public abstract FileItemDTO getFileItem(String path);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -4,31 +4,34 @@ import cn.hutool.core.util.URLUtil;
|
||||
import cn.hutool.http.HttpRequest;
|
||||
import cn.hutool.http.HttpResponse;
|
||||
import cn.hutool.http.HttpUtil;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import im.zhaojun.zfile.model.constant.ZFileConstant;
|
||||
import im.zhaojun.zfile.model.entity.StorageConfig;
|
||||
import im.zhaojun.zfile.model.constant.StorageConfigConstant;
|
||||
import im.zhaojun.zfile.model.constant.ZFileConstant;
|
||||
import im.zhaojun.zfile.model.dto.FileItemDTO;
|
||||
import im.zhaojun.zfile.model.entity.StorageConfig;
|
||||
import im.zhaojun.zfile.model.enums.FileTypeEnum;
|
||||
import im.zhaojun.zfile.model.support.OneDriveToken;
|
||||
import im.zhaojun.zfile.repository.StorageConfigRepository;
|
||||
import im.zhaojun.zfile.service.StorageConfigService;
|
||||
import im.zhaojun.zfile.util.StringUtils;
|
||||
import im.zhaojun.zfile.model.support.OneDriveToken;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.client.HttpClientErrorException;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Zhao Jun
|
||||
* 2020/1/29 11:54
|
||||
*/
|
||||
@Slf4j
|
||||
public abstract class AbstractOneDriveServiceBase extends AbstractBaseFileService {
|
||||
@@ -46,6 +49,7 @@ public abstract class AbstractOneDriveServiceBase extends AbstractBaseFileServic
|
||||
private static final String ONE_DRIVE_FILE_FLAG = "file";
|
||||
|
||||
@Resource
|
||||
@Lazy
|
||||
private RestTemplate oneDriveRestTemplate;
|
||||
|
||||
@Resource
|
||||
@@ -54,9 +58,14 @@ public abstract class AbstractOneDriveServiceBase extends AbstractBaseFileServic
|
||||
@Resource
|
||||
private StorageConfigService storageConfigService;
|
||||
|
||||
/**
|
||||
* 根据 RefreshToken 刷新 AccessToken, 返回刷新后的 Token.
|
||||
*
|
||||
* @return 刷新后的 Token
|
||||
*/
|
||||
public OneDriveToken getRefreshToken() {
|
||||
StorageConfig refreshStorageConfig =
|
||||
storageConfigRepository.findByTypeAndKey(this.getStorageTypeEnum(), StorageConfigConstant.REFRESH_TOKEN_KEY);
|
||||
storageConfigRepository.findByDriveIdAndKey(driveId, StorageConfigConstant.REFRESH_TOKEN_KEY);
|
||||
|
||||
String param = "client_id=" + getClientId() +
|
||||
"&redirect_uri=" + getRedirectUri() +
|
||||
@@ -72,6 +81,14 @@ public abstract class AbstractOneDriveServiceBase extends AbstractBaseFileServic
|
||||
return JSONObject.parseObject(response.body(), OneDriveToken.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* OAuth2 协议中, 根据 code 换取 access_token 和 refresh_token.
|
||||
*
|
||||
* @param code
|
||||
* 代码
|
||||
*
|
||||
* @return 获取的 Token 信息.
|
||||
*/
|
||||
public OneDriveToken getToken(String code) {
|
||||
String param = "client_id=" + getClientId() +
|
||||
"&redirect_uri=" + getRedirectUri() +
|
||||
@@ -88,10 +105,6 @@ public abstract class AbstractOneDriveServiceBase extends AbstractBaseFileServic
|
||||
return JSONObject.parseObject(response.body(), OneDriveToken.class);
|
||||
}
|
||||
|
||||
public String getUserInfo() {
|
||||
return oneDriveRestTemplate.getForObject(DRIVER_INFO_URL, String.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FileItemDTO> fileList(String path) {
|
||||
path = StringUtils.removeFirstSeparator(path);
|
||||
@@ -114,18 +127,23 @@ public abstract class AbstractOneDriveServiceBase extends AbstractBaseFileServic
|
||||
}
|
||||
fullPath = StringUtils.removeLastSeparator(fullPath);
|
||||
|
||||
ResponseEntity<String> responseEntity;
|
||||
JSONObject root;
|
||||
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.set("driveId", driveId.toString());
|
||||
HttpEntity<Object> entity = new HttpEntity<>(headers);
|
||||
|
||||
try {
|
||||
responseEntity = oneDriveRestTemplate.getForEntity(requestUrl, String.class, getGraphEndPoint(), fullPath);
|
||||
root = oneDriveRestTemplate.exchange(requestUrl, HttpMethod.GET, entity, JSONObject.class, getGraphEndPoint(), fullPath).getBody();
|
||||
} catch (HttpClientErrorException e) {
|
||||
log.debug("调用 OneDrive 时出现了网络异常: {} , 已尝试重新刷新 token 后再试.", e.getMessage());
|
||||
refreshOneDriveToken();
|
||||
responseEntity = oneDriveRestTemplate.getForEntity(requestUrl, String.class, getGraphEndPoint(), fullPath);
|
||||
root = oneDriveRestTemplate.exchange(requestUrl, HttpMethod.GET, entity, JSONObject.class, getGraphEndPoint(), fullPath).getBody();
|
||||
}
|
||||
|
||||
String body = responseEntity.getBody();
|
||||
|
||||
JSONObject root = JSON.parseObject(body);
|
||||
if (root == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
nextLink = root.getString("@odata.nextLink");
|
||||
|
||||
@@ -161,10 +179,15 @@ public abstract class AbstractOneDriveServiceBase extends AbstractBaseFileServic
|
||||
|
||||
String requestUrl;
|
||||
|
||||
ResponseEntity<String> responseEntity = oneDriveRestTemplate.getForEntity(DRIVER_ITEM_URL, String.class, getGraphEndPoint(), fullPath);
|
||||
String body = responseEntity.getBody();
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.set("driveId", driveId.toString());
|
||||
HttpEntity<Object> entity = new HttpEntity<>(headers);
|
||||
|
||||
JSONObject fileItem = JSON.parseObject(body);
|
||||
JSONObject fileItem = oneDriveRestTemplate.exchange(DRIVER_ITEM_URL, HttpMethod.GET, entity, JSONObject.class, getGraphEndPoint(), fullPath).getBody();
|
||||
|
||||
if (fileItem == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
FileItemDTO fileItemDTO = new FileItemDTO();
|
||||
fileItemDTO.setName(fileItem.getString("name"));
|
||||
@@ -203,12 +226,22 @@ public abstract class AbstractOneDriveServiceBase extends AbstractBaseFileServic
|
||||
}
|
||||
|
||||
StorageConfig accessTokenConfig =
|
||||
storageConfigService.selectByTypeAndKey(this.getStorageTypeEnum(), StorageConfigConstant.ACCESS_TOKEN_KEY);
|
||||
storageConfigService.findByDriveIdAndKey(driveId, StorageConfigConstant.ACCESS_TOKEN_KEY);
|
||||
StorageConfig refreshTokenConfig =
|
||||
storageConfigService.selectByTypeAndKey(this.getStorageTypeEnum(), StorageConfigConstant.REFRESH_TOKEN_KEY);
|
||||
storageConfigService.findByDriveIdAndKey(driveId, StorageConfigConstant.REFRESH_TOKEN_KEY);
|
||||
accessTokenConfig.setValue(refreshToken.getAccessToken());
|
||||
refreshTokenConfig.setValue(refreshToken.getRefreshToken());
|
||||
|
||||
storageConfigService.updateStorageConfig(Arrays.asList(accessTokenConfig, refreshTokenConfig));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<StorageConfig> storageStrategyConfigList() {
|
||||
return new ArrayList<StorageConfig>() {{
|
||||
add(new StorageConfig("accessToken", "访问令牌"));
|
||||
add(new StorageConfig("refreshToken", "刷新令牌"));
|
||||
add(new StorageConfig("basePath", "基路径"));
|
||||
}};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -6,10 +6,10 @@ import com.amazonaws.services.s3.AmazonS3;
|
||||
import com.amazonaws.services.s3.model.ListObjectsRequest;
|
||||
import com.amazonaws.services.s3.model.ObjectListing;
|
||||
import com.amazonaws.services.s3.model.S3ObjectSummary;
|
||||
import im.zhaojun.zfile.service.StorageConfigService;
|
||||
import im.zhaojun.zfile.exception.NotExistFileException;
|
||||
import im.zhaojun.zfile.model.dto.FileItemDTO;
|
||||
import im.zhaojun.zfile.model.enums.FileTypeEnum;
|
||||
import im.zhaojun.zfile.service.StorageConfigService;
|
||||
import im.zhaojun.zfile.util.StringUtils;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
@@ -93,6 +93,7 @@ public abstract class AbstractS3BaseFileService extends AbstractBaseFileService
|
||||
* @return S3 对象访问地址
|
||||
*/
|
||||
public String s3ObjectUrl(String path) {
|
||||
basePath = basePath == null ? "" : basePath;
|
||||
String fullPath = StringUtils.removeFirstSeparator(StringUtils.removeDuplicateSeparator(basePath + "/" + path));
|
||||
|
||||
// 如果不是私有空间, 且指定了加速域名, 则直接返回下载地址.
|
||||
|
||||
@@ -5,15 +5,19 @@ import com.amazonaws.auth.AWSStaticCredentialsProvider;
|
||||
import com.amazonaws.auth.BasicAWSCredentials;
|
||||
import com.amazonaws.client.builder.AwsClientBuilder;
|
||||
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
|
||||
import im.zhaojun.zfile.model.entity.StorageConfig;
|
||||
import im.zhaojun.zfile.model.constant.StorageConfigConstant;
|
||||
import im.zhaojun.zfile.model.entity.StorageConfig;
|
||||
import im.zhaojun.zfile.model.enums.StorageTypeEnum;
|
||||
import im.zhaojun.zfile.service.base.AbstractS3BaseFileService;
|
||||
import im.zhaojun.zfile.service.base.BaseFileService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
@@ -21,15 +25,17 @@ import java.util.Objects;
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Service
|
||||
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
|
||||
public class AliyunServiceImpl extends AbstractS3BaseFileService implements BaseFileService {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(AliyunServiceImpl.class);
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
public void init(Integer driveId) {
|
||||
try {
|
||||
this.driveId = driveId;
|
||||
Map<String, StorageConfig> stringStorageConfigMap =
|
||||
storageConfigService.selectStorageConfigMapByKey(getStorageTypeEnum());
|
||||
storageConfigService.selectStorageConfigMapByDriveId(driveId);
|
||||
String accessKey = stringStorageConfigMap.get(StorageConfigConstant.ACCESS_KEY).getValue();
|
||||
String secretKey = stringStorageConfigMap.get(StorageConfigConstant.SECRET_KEY).getValue();
|
||||
String endPoint = stringStorageConfigMap.get(StorageConfigConstant.ENDPOINT_KEY).getValue();
|
||||
@@ -51,7 +57,7 @@ public class AliyunServiceImpl extends AbstractS3BaseFileService implements Base
|
||||
isInitialized = testConnection();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.debug(getStorageTypeEnum().getDescription() + " 初始化异常, 已跳过");
|
||||
log.debug(getStorageTypeEnum().getDescription() + " 初始化异常, 已跳过", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,4 +66,16 @@ public class AliyunServiceImpl extends AbstractS3BaseFileService implements Base
|
||||
return StorageTypeEnum.ALIYUN;
|
||||
}
|
||||
|
||||
}
|
||||
@Override
|
||||
public List<StorageConfig> storageStrategyConfigList() {
|
||||
return new ArrayList<StorageConfig>() {{
|
||||
add(new StorageConfig("accessKey", "AccessKey"));
|
||||
add(new StorageConfig("secretKey", "SecretKey"));
|
||||
add(new StorageConfig("bucketName", "Bucket 名称"));
|
||||
add(new StorageConfig("domain", "Bucket 域名 / CDN 加速域名"));
|
||||
add(new StorageConfig("endPoint", "区域"));
|
||||
add(new StorageConfig("basePath", "基路径"));
|
||||
add(new StorageConfig("isPrivate", "是否是私有空间"));
|
||||
}};
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,8 @@ import org.apache.commons.net.ftp.FTPClientConfig;
|
||||
import org.apache.commons.net.ftp.FTPFile;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
@@ -29,6 +31,7 @@ import java.util.Objects;
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Service
|
||||
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
|
||||
public class FtpServiceImpl extends AbstractBaseFileService implements BaseFileService {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(FtpServiceImpl.class);
|
||||
@@ -49,10 +52,11 @@ public class FtpServiceImpl extends AbstractBaseFileService implements BaseFileS
|
||||
private String password;
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
public void init(Integer driveId) {
|
||||
try {
|
||||
this.driveId = driveId;
|
||||
Map<String, StorageConfig> stringStorageConfigMap =
|
||||
storageConfigService.selectStorageConfigMapByKey(getStorageTypeEnum());
|
||||
storageConfigService.selectStorageConfigMapByDriveId(driveId);
|
||||
host = stringStorageConfigMap.get(StorageConfigConstant.HOST_KEY).getValue();
|
||||
port = stringStorageConfigMap.get(StorageConfigConstant.PORT_KEY).getValue();
|
||||
username = stringStorageConfigMap.get(StorageConfigConstant.USERNAME_KEY).getValue();
|
||||
@@ -129,4 +133,16 @@ public class FtpServiceImpl extends AbstractBaseFileService implements BaseFileS
|
||||
fileItemDTO.setUrl(getDownloadUrl(path));
|
||||
return fileItemDTO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<StorageConfig> storageStrategyConfigList() {
|
||||
return new ArrayList<StorageConfig>() {{
|
||||
add(new StorageConfig("host", "域名或IP"));
|
||||
add(new StorageConfig("port", "端口"));
|
||||
add(new StorageConfig("username", "用户名"));
|
||||
add(new StorageConfig("password", "密码"));
|
||||
add(new StorageConfig("domain", "加速域名"));
|
||||
add(new StorageConfig("basePath", "基路径"));
|
||||
}};
|
||||
}
|
||||
}
|
||||
@@ -5,15 +5,19 @@ import com.amazonaws.auth.AWSStaticCredentialsProvider;
|
||||
import com.amazonaws.auth.BasicAWSCredentials;
|
||||
import com.amazonaws.client.builder.AwsClientBuilder;
|
||||
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
|
||||
import im.zhaojun.zfile.model.entity.StorageConfig;
|
||||
import im.zhaojun.zfile.model.constant.StorageConfigConstant;
|
||||
import im.zhaojun.zfile.model.entity.StorageConfig;
|
||||
import im.zhaojun.zfile.model.enums.StorageTypeEnum;
|
||||
import im.zhaojun.zfile.service.base.AbstractS3BaseFileService;
|
||||
import im.zhaojun.zfile.service.base.BaseFileService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
@@ -21,15 +25,17 @@ import java.util.Objects;
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Service
|
||||
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
|
||||
public class HuaweiServiceImpl extends AbstractS3BaseFileService implements BaseFileService {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(HuaweiServiceImpl.class);
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
public void init(Integer driveId) {
|
||||
try {
|
||||
this.driveId = driveId;
|
||||
Map<String, StorageConfig> stringStorageConfigMap =
|
||||
storageConfigService.selectStorageConfigMapByKey(getStorageTypeEnum());
|
||||
storageConfigService.selectStorageConfigMapByDriveId(driveId);
|
||||
String accessKey = stringStorageConfigMap.get(StorageConfigConstant.ACCESS_KEY).getValue();
|
||||
String secretKey = stringStorageConfigMap.get(StorageConfigConstant.SECRET_KEY).getValue();
|
||||
String endPoint = stringStorageConfigMap.get(StorageConfigConstant.ENDPOINT_KEY).getValue();
|
||||
@@ -60,4 +66,18 @@ public class HuaweiServiceImpl extends AbstractS3BaseFileService implements Base
|
||||
return StorageTypeEnum.HUAWEI;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<StorageConfig> storageStrategyConfigList() {
|
||||
return new ArrayList<StorageConfig>() {{
|
||||
add(new StorageConfig("accessKey", "AccessKey"));
|
||||
add(new StorageConfig("secretKey", "SecretKey"));
|
||||
add(new StorageConfig("bucketName", "云存储服务名称"));
|
||||
add(new StorageConfig("domain", "加速域名"));
|
||||
add(new StorageConfig("endPoint", "区域"));
|
||||
add(new StorageConfig("basePath", "基路径"));
|
||||
add(new StorageConfig("isPrivate", "是否是私有空间"));
|
||||
}};
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,24 +1,27 @@
|
||||
package im.zhaojun.zfile.service.impl;
|
||||
|
||||
import im.zhaojun.zfile.exception.NotExistFileException;
|
||||
import im.zhaojun.zfile.model.entity.StorageConfig;
|
||||
import im.zhaojun.zfile.model.entity.SystemConfig;
|
||||
import im.zhaojun.zfile.model.constant.StorageConfigConstant;
|
||||
import im.zhaojun.zfile.model.constant.SystemConfigConstant;
|
||||
import im.zhaojun.zfile.model.dto.FileItemDTO;
|
||||
import im.zhaojun.zfile.model.entity.StorageConfig;
|
||||
import im.zhaojun.zfile.model.entity.SystemConfig;
|
||||
import im.zhaojun.zfile.model.enums.FileTypeEnum;
|
||||
import im.zhaojun.zfile.model.enums.StorageTypeEnum;
|
||||
import im.zhaojun.zfile.repository.SystemConfigRepository;
|
||||
import im.zhaojun.zfile.service.StorageConfigService;
|
||||
import im.zhaojun.zfile.service.base.AbstractBaseFileService;
|
||||
import im.zhaojun.zfile.service.base.BaseFileService;
|
||||
import im.zhaojun.zfile.service.StorageConfigService;
|
||||
import im.zhaojun.zfile.util.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
@@ -29,6 +32,7 @@ import java.util.Objects;
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Service
|
||||
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
|
||||
public class LocalServiceImpl extends AbstractBaseFileService implements BaseFileService {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(LocalServiceImpl.class);
|
||||
@@ -42,10 +46,11 @@ public class LocalServiceImpl extends AbstractBaseFileService implements BaseFil
|
||||
private String filePath;
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
public void init(Integer driveId) {
|
||||
try {
|
||||
this.driveId = driveId;
|
||||
Map<String, StorageConfig> stringStorageConfigMap =
|
||||
storageConfigService.selectStorageConfigMapByKey(getStorageTypeEnum());
|
||||
storageConfigService.selectStorageConfigMapByDriveId(driveId);
|
||||
filePath = stringStorageConfigMap.get(StorageConfigConstant.FILE_PATH_KEY).getValue();
|
||||
if (Objects.isNull(filePath)) {
|
||||
log.debug("初始化存储策略 [{}] 失败: 参数不完整", getStorageTypeEnum().getDescription());
|
||||
@@ -59,12 +64,17 @@ public class LocalServiceImpl extends AbstractBaseFileService implements BaseFil
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FileItemDTO> fileList(String path) {
|
||||
public List<FileItemDTO> fileList(String path) throws FileNotFoundException {
|
||||
List<FileItemDTO> fileItemList = new ArrayList<>();
|
||||
|
||||
String fullPath = StringUtils.concatPath(filePath, path);
|
||||
|
||||
File file = new File(fullPath);
|
||||
|
||||
if (!file.exists()) {
|
||||
throw new FileNotFoundException("文件不存在");
|
||||
}
|
||||
|
||||
File[] files = file.listFiles();
|
||||
|
||||
if (files == null) {
|
||||
@@ -89,7 +99,7 @@ public class LocalServiceImpl extends AbstractBaseFileService implements BaseFil
|
||||
@Override
|
||||
public String getDownloadUrl(String path) {
|
||||
SystemConfig usernameConfig = systemConfigRepository.findByKey(SystemConfigConstant.DOMAIN);
|
||||
return StringUtils.removeDuplicateSeparator(usernameConfig.getValue() + "/file/" + path);
|
||||
return StringUtils.removeDuplicateSeparator(usernameConfig.getValue() + "/file/" + driveId + "/" + path);
|
||||
}
|
||||
|
||||
public String getFilePath() {
|
||||
@@ -127,4 +137,11 @@ public class LocalServiceImpl extends AbstractBaseFileService implements BaseFil
|
||||
|
||||
return fileItemDTO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<StorageConfig> storageStrategyConfigList() {
|
||||
return new ArrayList<StorageConfig>() {{
|
||||
add(new StorageConfig("filePath", "文件路径"));
|
||||
}};
|
||||
}
|
||||
}
|
||||
@@ -5,15 +5,19 @@ import com.amazonaws.auth.AWSStaticCredentialsProvider;
|
||||
import com.amazonaws.auth.BasicAWSCredentials;
|
||||
import com.amazonaws.client.builder.AwsClientBuilder;
|
||||
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
|
||||
import im.zhaojun.zfile.model.entity.StorageConfig;
|
||||
import im.zhaojun.zfile.model.constant.StorageConfigConstant;
|
||||
import im.zhaojun.zfile.model.entity.StorageConfig;
|
||||
import im.zhaojun.zfile.model.enums.StorageTypeEnum;
|
||||
import im.zhaojun.zfile.service.base.AbstractS3BaseFileService;
|
||||
import im.zhaojun.zfile.service.base.BaseFileService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
@@ -21,15 +25,17 @@ import java.util.Objects;
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Service
|
||||
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
|
||||
public class MinIOServiceImpl extends AbstractS3BaseFileService implements BaseFileService {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(MinIOServiceImpl.class);
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
public void init(Integer driveId) {
|
||||
try {
|
||||
this.driveId = driveId;
|
||||
Map<String, StorageConfig> stringStorageConfigMap =
|
||||
storageConfigService.selectStorageConfigMapByKey(getStorageTypeEnum());
|
||||
storageConfigService.selectStorageConfigMapByDriveId(driveId);
|
||||
String accessKey = stringStorageConfigMap.get(StorageConfigConstant.ACCESS_KEY).getValue();
|
||||
String secretKey = stringStorageConfigMap.get(StorageConfigConstant.SECRET_KEY).getValue();
|
||||
String endPoint = stringStorageConfigMap.get(StorageConfigConstant.ENDPOINT_KEY).getValue();
|
||||
@@ -61,4 +67,16 @@ public class MinIOServiceImpl extends AbstractS3BaseFileService implements BaseF
|
||||
return StorageTypeEnum.MINIO;
|
||||
}
|
||||
|
||||
}
|
||||
@Override
|
||||
public List<StorageConfig> storageStrategyConfigList() {
|
||||
return new ArrayList<StorageConfig>() {{
|
||||
add(new StorageConfig("accessKey", "AccessKey"));
|
||||
add(new StorageConfig("secretKey", "SecretKey"));
|
||||
add(new StorageConfig("endPoint", "服务地址"));
|
||||
add(new StorageConfig("bucketName", "存储空间名称"));
|
||||
add(new StorageConfig("basePath", "基路径"));
|
||||
add(new StorageConfig("isPrivate", "是否是私有空间"));
|
||||
}};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -8,6 +8,8 @@ import im.zhaojun.zfile.service.base.AbstractOneDriveServiceBase;
|
||||
import im.zhaojun.zfile.service.base.BaseFileService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
@@ -19,6 +21,7 @@ import java.util.Map;
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
|
||||
public class OneDriveChinaServiceImpl extends AbstractOneDriveServiceBase implements BaseFileService {
|
||||
|
||||
@Resource
|
||||
@@ -37,10 +40,11 @@ public class OneDriveChinaServiceImpl extends AbstractOneDriveServiceBase implem
|
||||
private String scope;
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
public void init(Integer driveId) {
|
||||
try {
|
||||
this.driveId = driveId;
|
||||
Map<String, StorageConfig> stringStorageConfigMap =
|
||||
storageConfigService.selectStorageConfigMapByKey(getStorageTypeEnum());
|
||||
storageConfigService.selectStorageConfigMapByDriveId(driveId);
|
||||
String accessToken = stringStorageConfigMap.get(StorageConfigConstant.ACCESS_TOKEN_KEY).getValue();
|
||||
String refreshToken = stringStorageConfigMap.get(StorageConfigConstant.REFRESH_TOKEN_KEY).getValue();
|
||||
super.basePath = stringStorageConfigMap.get(StorageConfigConstant.BASE_PATH).getValue();
|
||||
@@ -96,4 +100,5 @@ public class OneDriveChinaServiceImpl extends AbstractOneDriveServiceBase implem
|
||||
public String getScope() {
|
||||
return scope;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -8,6 +8,8 @@ import im.zhaojun.zfile.service.base.AbstractOneDriveServiceBase;
|
||||
import im.zhaojun.zfile.service.base.BaseFileService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
@@ -19,6 +21,7 @@ import java.util.Map;
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
|
||||
public class OneDriveServiceImpl extends AbstractOneDriveServiceBase implements BaseFileService {
|
||||
|
||||
@Resource
|
||||
@@ -37,10 +40,11 @@ public class OneDriveServiceImpl extends AbstractOneDriveServiceBase implements
|
||||
protected String scope;
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
public void init(Integer driveId) {
|
||||
try {
|
||||
this.driveId = driveId;
|
||||
Map<String, StorageConfig> stringStorageConfigMap =
|
||||
storageConfigService.selectStorageConfigMapByKey(getStorageTypeEnum());
|
||||
storageConfigService.selectStorageConfigMapByDriveId(driveId);
|
||||
String accessToken = stringStorageConfigMap.get(StorageConfigConstant.ACCESS_TOKEN_KEY).getValue();
|
||||
String refreshToken = stringStorageConfigMap.get(StorageConfigConstant.REFRESH_TOKEN_KEY).getValue();
|
||||
super.basePath = stringStorageConfigMap.get(StorageConfigConstant.BASE_PATH).getValue();
|
||||
|
||||
@@ -5,15 +5,19 @@ import com.amazonaws.auth.AWSStaticCredentialsProvider;
|
||||
import com.amazonaws.auth.BasicAWSCredentials;
|
||||
import com.amazonaws.client.builder.AwsClientBuilder;
|
||||
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
|
||||
import im.zhaojun.zfile.model.entity.StorageConfig;
|
||||
import im.zhaojun.zfile.model.constant.StorageConfigConstant;
|
||||
import im.zhaojun.zfile.model.entity.StorageConfig;
|
||||
import im.zhaojun.zfile.model.enums.StorageTypeEnum;
|
||||
import im.zhaojun.zfile.service.base.AbstractS3BaseFileService;
|
||||
import im.zhaojun.zfile.service.base.BaseFileService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
@@ -21,15 +25,17 @@ import java.util.Objects;
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Service
|
||||
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
|
||||
public class QiniuServiceImpl extends AbstractS3BaseFileService implements BaseFileService {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(QiniuServiceImpl.class);
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
public void init(Integer driveId) {
|
||||
try {
|
||||
this.driveId = driveId;
|
||||
Map<String, StorageConfig> stringStorageConfigMap =
|
||||
storageConfigService.selectStorageConfigMapByKey(getStorageTypeEnum());
|
||||
storageConfigService.selectStorageConfigMapByDriveId(driveId);
|
||||
String accessKey = stringStorageConfigMap.get(StorageConfigConstant.ACCESS_KEY).getValue();
|
||||
String secretKey = stringStorageConfigMap.get(StorageConfigConstant.SECRET_KEY).getValue();
|
||||
String endPoint = stringStorageConfigMap.get(StorageConfigConstant.ENDPOINT_KEY).getValue();
|
||||
@@ -60,4 +66,17 @@ public class QiniuServiceImpl extends AbstractS3BaseFileService implements BaseF
|
||||
return StorageTypeEnum.QINIU;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<StorageConfig> storageStrategyConfigList() {
|
||||
return new ArrayList<StorageConfig>() {{
|
||||
add(new StorageConfig("accessKey", "AccessKey"));
|
||||
add(new StorageConfig("secretKey", "SecretKey"));
|
||||
add(new StorageConfig("bucketName", "存储空间名称"));
|
||||
add(new StorageConfig("domain", "加速域名"));
|
||||
add(new StorageConfig("endPoint", "区域"));
|
||||
add(new StorageConfig("basePath", "基路径"));
|
||||
add(new StorageConfig("isPrivate", "是否是私有空间"));
|
||||
}};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -5,15 +5,19 @@ import com.amazonaws.auth.AWSStaticCredentialsProvider;
|
||||
import com.amazonaws.auth.BasicAWSCredentials;
|
||||
import com.amazonaws.client.builder.AwsClientBuilder;
|
||||
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
|
||||
import im.zhaojun.zfile.model.entity.StorageConfig;
|
||||
import im.zhaojun.zfile.model.constant.StorageConfigConstant;
|
||||
import im.zhaojun.zfile.model.entity.StorageConfig;
|
||||
import im.zhaojun.zfile.model.enums.StorageTypeEnum;
|
||||
import im.zhaojun.zfile.service.base.AbstractS3BaseFileService;
|
||||
import im.zhaojun.zfile.service.base.BaseFileService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
@@ -21,15 +25,17 @@ import java.util.Objects;
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Service
|
||||
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
|
||||
public class S3ServiceImpl extends AbstractS3BaseFileService implements BaseFileService {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(S3ServiceImpl.class);
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
public void init(Integer driveId) {
|
||||
try {
|
||||
this.driveId = driveId;
|
||||
Map<String, StorageConfig> stringStorageConfigMap =
|
||||
storageConfigService.selectStorageConfigMapByKey(getStorageTypeEnum());
|
||||
storageConfigService.selectStorageConfigMapByDriveId(driveId);
|
||||
String accessKey = stringStorageConfigMap.get(StorageConfigConstant.ACCESS_KEY).getValue();
|
||||
String secretKey = stringStorageConfigMap.get(StorageConfigConstant.SECRET_KEY).getValue();
|
||||
String endPoint = stringStorageConfigMap.get(StorageConfigConstant.ENDPOINT_KEY).getValue();
|
||||
@@ -65,4 +71,17 @@ public class S3ServiceImpl extends AbstractS3BaseFileService implements BaseFile
|
||||
return StorageTypeEnum.S3;
|
||||
}
|
||||
|
||||
}
|
||||
@Override
|
||||
public List<StorageConfig> storageStrategyConfigList() {
|
||||
return new ArrayList<StorageConfig>() {{
|
||||
add(new StorageConfig("accessKey", "AccessKey"));
|
||||
add(new StorageConfig("secretKey", "SecretKey"));
|
||||
add(new StorageConfig("endPoint", "服务地址(EndPoint)"));
|
||||
add(new StorageConfig("bucketName", "存储空间名称"));
|
||||
add(new StorageConfig("basePath", "基路径"));
|
||||
add(new StorageConfig("domain", "加速域名"));
|
||||
add(new StorageConfig("pathStyle", "域名风格"));
|
||||
add(new StorageConfig("isPrivate", "是否是私有空间"));
|
||||
}};
|
||||
}
|
||||
}
|
||||
@@ -5,15 +5,19 @@ import com.amazonaws.auth.AWSStaticCredentialsProvider;
|
||||
import com.amazonaws.auth.BasicAWSCredentials;
|
||||
import com.amazonaws.client.builder.AwsClientBuilder;
|
||||
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
|
||||
import im.zhaojun.zfile.model.entity.StorageConfig;
|
||||
import im.zhaojun.zfile.model.constant.StorageConfigConstant;
|
||||
import im.zhaojun.zfile.model.entity.StorageConfig;
|
||||
import im.zhaojun.zfile.model.enums.StorageTypeEnum;
|
||||
import im.zhaojun.zfile.service.base.AbstractS3BaseFileService;
|
||||
import im.zhaojun.zfile.service.base.BaseFileService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
@@ -21,15 +25,17 @@ import java.util.Objects;
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Service
|
||||
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
|
||||
public class TencentServiceImpl extends AbstractS3BaseFileService implements BaseFileService {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(TencentServiceImpl.class);
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
public void init(Integer driveId) {
|
||||
try {
|
||||
this.driveId = driveId;
|
||||
Map<String, StorageConfig> stringStorageConfigMap =
|
||||
storageConfigService.selectStorageConfigMapByKey(getStorageTypeEnum());
|
||||
storageConfigService.selectStorageConfigMapByDriveId(driveId);
|
||||
String secretId = stringStorageConfigMap.get(StorageConfigConstant.SECRET_ID_KEY).getValue();
|
||||
String secretKey = stringStorageConfigMap.get(StorageConfigConstant.SECRET_KEY).getValue();
|
||||
String endPoint = stringStorageConfigMap.get(StorageConfigConstant.ENDPOINT_KEY).getValue();
|
||||
@@ -55,10 +61,21 @@ public class TencentServiceImpl extends AbstractS3BaseFileService implements Bas
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public StorageTypeEnum getStorageTypeEnum() {
|
||||
return StorageTypeEnum.TENCENT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<StorageConfig> storageStrategyConfigList() {
|
||||
return new ArrayList<StorageConfig>() {{
|
||||
add(new StorageConfig("secretId", "SecretId"));
|
||||
add(new StorageConfig("secretKey", "SecretKey"));
|
||||
add(new StorageConfig("bucketName", "云存储服务名称"));
|
||||
add(new StorageConfig("domain", "加速域名"));
|
||||
add(new StorageConfig("endPoint", "区域"));
|
||||
add(new StorageConfig("basePath", "基路径"));
|
||||
add(new StorageConfig("isPrivate", "是否是私有空间"));
|
||||
}};
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,15 @@
|
||||
package im.zhaojun.zfile.service.impl;
|
||||
|
||||
import im.zhaojun.zfile.model.enums.StorageTypeEnum;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Service
|
||||
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
|
||||
public class UFileServiceImpl extends UpYunServiceImpl {
|
||||
|
||||
@Override
|
||||
|
||||
@@ -3,21 +3,26 @@ package im.zhaojun.zfile.service.impl;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.URLUtil;
|
||||
import com.UpYun;
|
||||
import com.upyun.UpException;
|
||||
import im.zhaojun.zfile.exception.NotExistFileException;
|
||||
import im.zhaojun.zfile.model.entity.StorageConfig;
|
||||
import im.zhaojun.zfile.model.constant.StorageConfigConstant;
|
||||
import im.zhaojun.zfile.model.dto.FileItemDTO;
|
||||
import im.zhaojun.zfile.model.entity.StorageConfig;
|
||||
import im.zhaojun.zfile.model.enums.FileTypeEnum;
|
||||
import im.zhaojun.zfile.model.enums.StorageTypeEnum;
|
||||
import im.zhaojun.zfile.service.StorageConfigService;
|
||||
import im.zhaojun.zfile.service.base.AbstractBaseFileService;
|
||||
import im.zhaojun.zfile.service.base.BaseFileService;
|
||||
import im.zhaojun.zfile.service.StorageConfigService;
|
||||
import im.zhaojun.zfile.util.StringUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -28,6 +33,7 @@ import java.util.Objects;
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
|
||||
public class UpYunServiceImpl extends AbstractBaseFileService implements BaseFileService {
|
||||
|
||||
private static final String END_MARK = "g2gCZAAEbmV4dGQAA2VvZg";
|
||||
@@ -42,10 +48,11 @@ public class UpYunServiceImpl extends AbstractBaseFileService implements BaseFil
|
||||
private String basePath;
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
public void init(Integer driveId) {
|
||||
try {
|
||||
this.driveId = driveId;
|
||||
Map<String, StorageConfig> stringStorageConfigMap =
|
||||
storageConfigService.selectStorageConfigMapByKey(getStorageTypeEnum());
|
||||
storageConfigService.selectStorageConfigMapByDriveId(driveId);
|
||||
String bucketName = stringStorageConfigMap.get(StorageConfigConstant.BUCKET_NAME_KEY).getValue();
|
||||
String username = stringStorageConfigMap.get(StorageConfigConstant.USERNAME_KEY).getValue();
|
||||
String password = stringStorageConfigMap.get(StorageConfigConstant.PASSWORD_KEY).getValue();
|
||||
@@ -111,21 +118,45 @@ public class UpYunServiceImpl extends AbstractBaseFileService implements BaseFil
|
||||
|
||||
@Override
|
||||
public FileItemDTO getFileItem(String path) {
|
||||
List<FileItemDTO> list;
|
||||
try {
|
||||
int end = path.lastIndexOf("/");
|
||||
list = fileList(path.substring(0, end));
|
||||
} catch (Exception e) {
|
||||
throw new NotExistFileException();
|
||||
}
|
||||
int lastDelimiterIndex = path.lastIndexOf("/");
|
||||
String name = path.substring(lastDelimiterIndex + 1);
|
||||
|
||||
for (FileItemDTO fileItemDTO : list) {
|
||||
String fullPath = StringUtils.concatUrl(fileItemDTO.getPath(), fileItemDTO.getName());
|
||||
if (Objects.equals(fullPath, path)) {
|
||||
return fileItemDTO;
|
||||
Map<String, String> fileInfo = upYun.getFileInfo(StringUtils.removeDuplicateSeparator(basePath + "/" + path));
|
||||
|
||||
if (fileInfo == null) {
|
||||
throw new NotExistFileException();
|
||||
}
|
||||
|
||||
FileItemDTO fileItemDTO = new FileItemDTO();
|
||||
fileItemDTO.setName(name);
|
||||
fileItemDTO.setSize(Long.valueOf(fileInfo.get("size")));
|
||||
fileItemDTO.setTime(new Date(Long.parseLong(fileInfo.get("date")) * 1000));
|
||||
fileItemDTO.setPath(path);
|
||||
|
||||
if ("folder".equals(fileInfo.get("type"))) {
|
||||
fileItemDTO.setType(FileTypeEnum.FOLDER);
|
||||
} else {
|
||||
fileItemDTO.setType(FileTypeEnum.FILE);
|
||||
fileItemDTO.setUrl(getDownloadUrl(StringUtils.removeDuplicateSeparator(basePath + "/" + path)));
|
||||
}
|
||||
return fileItemDTO;
|
||||
} catch (IOException | UpException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
throw new NotExistFileException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<StorageConfig> storageStrategyConfigList() {
|
||||
return new ArrayList<StorageConfig>() {{
|
||||
add(new StorageConfig("bucketName", "云存储服务名称"));
|
||||
add(new StorageConfig("username", "操作员名称"));
|
||||
add(new StorageConfig("password", "操作员密码"));
|
||||
add(new StorageConfig("domain", "加速域名"));
|
||||
add(new StorageConfig("basePath", "基路径"));
|
||||
}};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,191 +0,0 @@
|
||||
package im.zhaojun.zfile.service.support;
|
||||
|
||||
import im.zhaojun.zfile.cache.ZFileCache;
|
||||
import im.zhaojun.zfile.config.StorageTypeFactory;
|
||||
import im.zhaojun.zfile.model.dto.FileItemDTO;
|
||||
import im.zhaojun.zfile.model.enums.FileTypeEnum;
|
||||
import im.zhaojun.zfile.model.enums.StorageTypeEnum;
|
||||
import im.zhaojun.zfile.service.SystemConfigService;
|
||||
import im.zhaojun.zfile.service.base.AbstractBaseFileService;
|
||||
import im.zhaojun.zfile.service.base.BaseFileService;
|
||||
import im.zhaojun.zfile.util.StringUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class FileAsyncCacheService {
|
||||
|
||||
public static final String CACHE_PROCESS_PREFIX = "zfile-process-cache:";
|
||||
|
||||
private boolean cacheFinish;
|
||||
|
||||
@Resource
|
||||
private SystemConfigService systemConfigService;
|
||||
|
||||
private volatile boolean stopFlag = false;
|
||||
|
||||
@Resource
|
||||
private ZFileCache zFileCache;
|
||||
|
||||
@Value("${zfile.cache.auto-refresh.enable}")
|
||||
protected boolean enableAutoRefreshCache;
|
||||
|
||||
@Value("${zfile.cache.auto-refresh.delay}")
|
||||
protected Long delay;
|
||||
|
||||
@Value("${zfile.cache.auto-refresh.interval}")
|
||||
protected Long interval;
|
||||
|
||||
@Async
|
||||
public void cacheGlobalFile() {
|
||||
stopFlag = false;
|
||||
StorageTypeEnum storageStrategy = systemConfigService.getCurrentStorageStrategy();
|
||||
|
||||
if (storageStrategy == null) {
|
||||
log.debug("尚未配置存储策略. 跳过启动缓存.");
|
||||
return;
|
||||
}
|
||||
|
||||
boolean enableCache = systemConfigService.getEnableCache();
|
||||
if (!enableCache) {
|
||||
log.debug("存储策略 {} 未启用缓存, 跳过缓存.", storageStrategy.getDescription());
|
||||
return;
|
||||
}
|
||||
|
||||
AbstractBaseFileService fileService = StorageTypeFactory.getStorageTypeService(storageStrategy);
|
||||
|
||||
if (fileService.getIsUnInitialized()) {
|
||||
log.debug("存储策略 {} 未初始化成功, 跳过缓存.", storageStrategy.getDescription());
|
||||
return;
|
||||
}
|
||||
|
||||
log.info("缓存 {} 所有文件开始", storageStrategy.getDescription());
|
||||
long startTime = System.currentTimeMillis();
|
||||
try {
|
||||
BaseFileService currentFileService = systemConfigService.getCurrentFileService();
|
||||
List<FileItemDTO> rootFileItems = currentFileService.fileList("/");
|
||||
ArrayDeque<FileItemDTO> queue = new ArrayDeque<>(rootFileItems);
|
||||
|
||||
while (!queue.isEmpty()) {
|
||||
FileItemDTO fileItemDTO = queue.pop();
|
||||
|
||||
if (stopFlag) {
|
||||
zFileCache.clear();
|
||||
break;
|
||||
}
|
||||
|
||||
if (fileItemDTO.getType() == FileTypeEnum.FOLDER) {
|
||||
String filePath = StringUtils.removeDuplicateSeparator("/" + fileItemDTO.getPath() + "/" + fileItemDTO.getName() + "/");
|
||||
|
||||
List<FileItemDTO> fileItems = currentFileService.fileList(filePath);
|
||||
queue.addAll(fileItems);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("缓存所有文件失败", e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
long endTime = System.currentTimeMillis();
|
||||
|
||||
if (stopFlag) {
|
||||
log.info("缓存 {} 所有文件被强制结束, 用时: {} 秒", storageStrategy.getDescription(), ((endTime - startTime) / 1000));
|
||||
cacheFinish = false;
|
||||
stopFlag = false;
|
||||
} else {
|
||||
log.info("缓存 {} 所有文件结束, 用时: {} 秒", storageStrategy.getDescription(), ((endTime - startTime) / 1000));
|
||||
enableCacheAutoRefreshTask();
|
||||
cacheFinish = true;
|
||||
stopFlag = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void enableCacheAutoRefreshTask() {
|
||||
StorageTypeEnum currentStorageStrategy = systemConfigService.getCurrentStorageStrategy();
|
||||
|
||||
if (enableAutoRefreshCache) {
|
||||
ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
|
||||
scheduledExecutorService.scheduleWithFixedDelay(() -> {
|
||||
zFileCache.setLastCacheAutoRefreshDate(new Date());
|
||||
|
||||
boolean enableCache = systemConfigService.getEnableCache();
|
||||
|
||||
if (!enableCache) {
|
||||
log.debug("当前存储引擎未开启缓存, 跳过自动刷新缓存");
|
||||
zFileCache.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
log.debug("开始调用自动刷新缓存");
|
||||
|
||||
Set<String> keySet = zFileCache.keySet();
|
||||
|
||||
ArrayList<String> keys = new ArrayList<>(keySet);
|
||||
|
||||
|
||||
for (String key : keys) {
|
||||
try {
|
||||
Thread.sleep(300);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
if (stopFlag) {
|
||||
break;
|
||||
}
|
||||
|
||||
zFileCache.remove(key);
|
||||
AbstractBaseFileService currentFileService = systemConfigService.getCurrentFileService();
|
||||
try {
|
||||
if (Objects.equals(currentStorageStrategy, systemConfigService.getCurrentStorageStrategy())) {
|
||||
currentFileService.fileList(key);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("刷新过程中出错 : [" + key + "]", e);
|
||||
}
|
||||
}
|
||||
|
||||
if (stopFlag) {
|
||||
log.debug("检测到停止 [{}] 缓存指令, 已停止自动刷新任务", currentStorageStrategy);
|
||||
scheduledExecutorService.shutdownNow();
|
||||
stopFlag = false;
|
||||
} else {
|
||||
log.debug("自动刷新缓存完成");
|
||||
}
|
||||
}, delay, interval, TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
public void stopScheduled() {
|
||||
this.stopFlag = true;
|
||||
}
|
||||
|
||||
public void enableScheduled() {
|
||||
this.stopFlag = false;
|
||||
}
|
||||
|
||||
public boolean isCacheFinish() {
|
||||
return cacheFinish;
|
||||
}
|
||||
|
||||
public void setCacheFinish(boolean cacheFinish) {
|
||||
this.cacheFinish = cacheFinish;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
package im.zhaojun.zfile.service.support;
|
||||
|
||||
import im.zhaojun.zfile.cache.ZFileCache;
|
||||
import im.zhaojun.zfile.service.SystemConfigService;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
/**
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Service
|
||||
public class FileCacheService {
|
||||
|
||||
@Resource
|
||||
private SystemConfigService systemConfigService;
|
||||
|
||||
@Resource
|
||||
@Lazy
|
||||
private FileAsyncCacheService fileAsyncCacheService;
|
||||
|
||||
@Resource
|
||||
private ZFileCache zFileCache;
|
||||
|
||||
public void enableCache() {
|
||||
systemConfigService.updateCacheEnableConfig(true);
|
||||
fileAsyncCacheService.cacheGlobalFile();
|
||||
}
|
||||
|
||||
public void disableCache() {
|
||||
systemConfigService.updateCacheEnableConfig(false);
|
||||
zFileCache.clear();
|
||||
fileAsyncCacheService.setCacheFinish(false);
|
||||
fileAsyncCacheService.stopScheduled();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -35,6 +35,12 @@ public class AudioHelper {
|
||||
url = url.replace(query, URLUtil.encode(query));
|
||||
}
|
||||
|
||||
// 如果音乐文件大小超出 5M, 则不解析此音乐
|
||||
if (im.zhaojun.zfile.util.HttpUtil.getRemoteFileSize(url)
|
||||
> (1024 * 1024 * ZFileConstant.AUDIO_MAX_FILE_SIZE_MB)) {
|
||||
return AudioInfoDTO.buildDefaultAudioInfoDTO();
|
||||
}
|
||||
|
||||
File file = new File(ZFileConstant.USER_HOME + ZFileConstant.AUDIO_TMP_PATH + UUID.fastUUID());
|
||||
FileUtil.mkParentDirs(file);
|
||||
HttpUtil.downloadFile(url, file);
|
||||
@@ -45,10 +51,7 @@ public class AudioHelper {
|
||||
}
|
||||
|
||||
private static AudioInfoDTO parseAudioInfo(File file) throws IOException, UnsupportedTagException {
|
||||
AudioInfoDTO audioInfoDTO = new AudioInfoDTO();
|
||||
audioInfoDTO.setTitle("未知歌曲");
|
||||
audioInfoDTO.setArtist("未知");
|
||||
audioInfoDTO.setCover("http://c.jun6.net/audio.png");
|
||||
AudioInfoDTO audioInfoDTO = AudioInfoDTO.buildDefaultAudioInfoDTO();
|
||||
|
||||
Mp3File mp3File = null;
|
||||
try {
|
||||
|
||||
@@ -1,29 +1,49 @@
|
||||
package im.zhaojun.zfile.util;
|
||||
|
||||
import im.zhaojun.zfile.exception.PreviewException;
|
||||
import im.zhaojun.zfile.model.constant.ZFileConstant;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.client.RestClientException;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
|
||||
/**
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Slf4j
|
||||
public class HttpUtil {
|
||||
|
||||
/**
|
||||
* 最大支持文件预览大小: 1M
|
||||
*/
|
||||
public static String getTextContent(String url) {
|
||||
RestTemplate restTemplate = SpringContextHolder.getBean("restTemplate");
|
||||
|
||||
if (getRemoteFileSize(url) > (1024 * ZFileConstant.TEXT_MAX_FILE_SIZE_KB)) {
|
||||
throw new PreviewException("存储源跨域请求失败, 服务器中转状态, 预览文件超出大小, 最大支持 1M");
|
||||
}
|
||||
|
||||
String result = restTemplate.getForObject(url, String.class);
|
||||
return result == null ? "" : result;
|
||||
}
|
||||
|
||||
public static boolean checkUrlExist(String url) {
|
||||
RestTemplate restTemplate = SpringContextHolder.getBean("restTemplate");
|
||||
/**
|
||||
* 获取远程文件大小
|
||||
*/
|
||||
public static Long getRemoteFileSize(String url) {
|
||||
long size = 0;
|
||||
URL urlObject;
|
||||
try {
|
||||
restTemplate.headForHeaders(url);
|
||||
return true;
|
||||
} catch (RestClientException ignored) {
|
||||
urlObject = new URL(url);
|
||||
URLConnection conn = urlObject.openConnection();
|
||||
size = conn.getContentLength();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -6,15 +6,15 @@ import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Service
|
||||
@Lazy(false)
|
||||
public class SpringContextHolder implements ApplicationContextAware, DisposableBean {
|
||||
|
||||
private static ApplicationContext applicationContext = null;
|
||||
@@ -67,4 +67,8 @@ public class SpringContextHolder implements ApplicationContextAware, DisposableB
|
||||
SpringContextHolder.applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
public static <T> Map<String, T> getBeansOfType(Class<T> classz) {
|
||||
return applicationContext.getBeansOfType(classz);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,8 +1,6 @@
|
||||
package im.zhaojun.zfile.util;
|
||||
|
||||
import cn.hutool.core.net.NetUtil;
|
||||
import im.zhaojun.zfile.exception.InitializeException;
|
||||
import im.zhaojun.zfile.service.support.FileAsyncCacheService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.boot.context.event.ApplicationStartedEvent;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
@@ -21,16 +19,12 @@ import java.util.LinkedHashSet;
|
||||
@Slf4j
|
||||
public class StartupListener implements ApplicationListener<ApplicationStartedEvent> {
|
||||
|
||||
@Resource
|
||||
private FileAsyncCacheService fileAsyncCacheService;
|
||||
|
||||
@Resource
|
||||
private Environment environment;
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(@NonNull ApplicationStartedEvent event) {
|
||||
printStartInfo();
|
||||
cacheAllFile();
|
||||
}
|
||||
|
||||
|
||||
@@ -49,11 +43,11 @@ public class StartupListener implements ApplicationListener<ApplicationStartedEv
|
||||
log.info("ZFile Admin started at " + indexAdminAddr);
|
||||
}
|
||||
|
||||
private void cacheAllFile() {
|
||||
try {
|
||||
fileAsyncCacheService.cacheGlobalFile();
|
||||
} catch (Exception e) {
|
||||
throw new InitializeException("初始化缓存异常.", e);
|
||||
}
|
||||
}
|
||||
// private void cacheAllFile() {
|
||||
// try {
|
||||
// fileAsyncCacheService.cacheGlobalFile();
|
||||
// } catch (Exception e) {
|
||||
// throw new InitializeException("初始化缓存异常.", e);
|
||||
// }
|
||||
// }
|
||||
}
|
||||
@@ -71,6 +71,16 @@
|
||||
"name": "zfile.onedrive-china.scope",
|
||||
"type": "java.lang.String",
|
||||
"description": "OneDrive China 认证权限."
|
||||
},
|
||||
{
|
||||
"name": "zfile.preview.audio.maxFileSizeMb",
|
||||
"type": "java.lang.Long",
|
||||
"description": "允许在线解析封面, 专辑, 歌手信息的音频文件大小, 单位为 KB."
|
||||
},
|
||||
{
|
||||
"name": "zfile.preview.text.maxFileSizeKb",
|
||||
"type": "java.lang.Long",
|
||||
"description": "允许在线读取文本文件的文件大小, 单位为 KB."
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -24,7 +24,7 @@ spring:
|
||||
|
||||
# h2 内存数据库 配置
|
||||
driver-class-name: org.h2.Driver
|
||||
url: jdbc:h2:~/.zfile/db/zfile
|
||||
url: jdbc:h2:~/.zfile-new/db/zfile
|
||||
username: zfile
|
||||
password: 123456
|
||||
|
||||
@@ -51,14 +51,19 @@ spring:
|
||||
|
||||
zfile:
|
||||
cache:
|
||||
auto-refresh:
|
||||
enable: true # 是否开启自动刷新缓存.
|
||||
delay: 1800 # 启动项目后多久开始自动刷新缓存, 推荐与 interval 一致, 因为项目启动时会缓存所有文件.
|
||||
interval: 1800 # 任务间隔时间, 也就是每多长时间会自动刷新缓存一次.
|
||||
# auto-refresh: # 新版本尚未实现此功能
|
||||
# enable: true # 是否开启自动刷新缓存.
|
||||
# delay: 1800 # 启动项目后多久开始自动刷新缓存, 推荐与 interval 一致, 因为项目启动时会缓存所有文件.
|
||||
# interval: 1800 # 任务间隔时间, 也就是每多长时间会自动刷新缓存一次.
|
||||
timeout: 1800
|
||||
constant:
|
||||
readme: readme.md
|
||||
password: password.txt
|
||||
preview:
|
||||
audio:
|
||||
maxFileSizeMb: 5
|
||||
text:
|
||||
maxFileSizeKb: 512
|
||||
onedrive:
|
||||
clientId: 09939809-c617-43c8-a220-a93c1513c5d4
|
||||
clientSecret: _l:zI-_yrW75lV8M61K@z.I2K@B/On6Q
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
INSERT INTO SYSTEM_CONFIG (`ID`, `k`, `REMARK`) VALUES (1, 'siteName', '站点名称');
|
||||
INSERT INTO SYSTEM_CONFIG (`ID`, `k`, `REMARK`) VALUES (2, 'infoEnable', '是否开启信息框');
|
||||
INSERT INTO SYSTEM_CONFIG (`ID`, `k`, `REMARK`) VALUES (3, 'searchEnable', '是否开启搜索');
|
||||
INSERT INTO SYSTEM_CONFIG (`ID`, `k`, `REMARK`) VALUES (4, 'searchIgnoreCase', '是否搜索时忽略大小写');
|
||||
INSERT INTO SYSTEM_CONFIG (`ID`, `k`, `REMARK`) VALUES (5, 'storageStrategy', '当前启用存储引擎');
|
||||
INSERT INTO SYSTEM_CONFIG (`ID`, `k`, `REMARK`) VALUES (6, 'username', '管理员账号');
|
||||
INSERT INTO SYSTEM_CONFIG (`ID`, `k`, `REMARK`) VALUES (7, 'password', '管理员密码');
|
||||
INSERT INTO SYSTEM_CONFIG (`ID`, `k`, `REMARK`) VALUES (8, 'domain', '站点域名');
|
||||
INSERT INTO SYSTEM_CONFIG (`ID`, `k`, `REMARK`) VALUES (9, 'enableCache', '是否开启缓存');
|
||||
INSERT INTO SYSTEM_CONFIG (`ID`, `k`, `REMARK`) VALUES (10, 'searchContainEncryptedFile', '搜索包含加密文件');
|
||||
INSERT INTO SYSTEM_CONFIG (`ID`, `k`, `REMARK`) VALUES (11, 'customCss', '自定义 CSS');
|
||||
INSERT INTO SYSTEM_CONFIG (`ID`, `k`, `REMARK`) VALUES (12, 'customJs', '自定义 JS (可用于统计代码)');
|
||||
INSERT INTO SYSTEM_CONFIG (`ID`, `k`, `REMARK`) VALUES (13, 'tableSize', '表格大小');
|
||||
@@ -15,72 +10,4 @@ INSERT INTO SYSTEM_CONFIG (`ID`, `k`, `REMARK`) VALUES (14, 'showOperator', '是
|
||||
INSERT INTO SYSTEM_CONFIG (`ID`, `k`, `REMARK`) VALUES (15, 'showDocument', '是否显示文档');
|
||||
INSERT INTO SYSTEM_CONFIG (`ID`, `k`, `REMARK`) VALUES (16, 'announcement', '网站公告');
|
||||
INSERT INTO SYSTEM_CONFIG (`ID`, `k`, `REMARK`) VALUES (17, 'showAnnouncement', '是否显示网站公告');
|
||||
INSERT INTO SYSTEM_CONFIG (`ID`, `k`, `REMARK`) VALUES (18, 'layout', '页面布局');
|
||||
|
||||
INSERT INTO STORAGE_CONFIG (`ID`, `k`, `TITLE`, `TYPE`) VALUES (1, 'bucket-name', '云存储服务名称', 'upyun');
|
||||
INSERT INTO STORAGE_CONFIG (`ID`, `k`, `TITLE`, `TYPE`) VALUES (2, 'username', '操作员名称', 'upyun');
|
||||
INSERT INTO STORAGE_CONFIG (`ID`, `k`, `TITLE`, `TYPE`) VALUES (3, 'password', '操作员密码', 'upyun');
|
||||
INSERT INTO STORAGE_CONFIG (`ID`, `k`, `TITLE`, `TYPE`) VALUES (4, 'domain', '加速域名', 'upyun');
|
||||
INSERT INTO STORAGE_CONFIG (`ID`, `k`, `TITLE`, `TYPE`) VALUES (5, 'accessKey', 'AccessKey', 'qiniu');
|
||||
INSERT INTO STORAGE_CONFIG (`ID`, `k`, `TITLE`, `TYPE`) VALUES (6, 'secretKey', 'SecretKey', 'qiniu');
|
||||
INSERT INTO STORAGE_CONFIG (`ID`, `k`, `TITLE`, `TYPE`) VALUES (7, 'bucket-name', '存储空间名称', 'qiniu');
|
||||
INSERT INTO STORAGE_CONFIG (`ID`, `k`, `TITLE`, `TYPE`) VALUES (8, 'domain', '加速域名', 'qiniu');
|
||||
INSERT INTO STORAGE_CONFIG (`ID`, `k`, `TITLE`, `TYPE`) VALUES (9, 'accessKey', 'AccessKey', 'huawei');
|
||||
INSERT INTO STORAGE_CONFIG (`ID`, `k`, `TITLE`, `TYPE`) VALUES (10, 'secretKey', 'SecretKey', 'huawei');
|
||||
INSERT INTO STORAGE_CONFIG (`ID`, `k`, `TITLE`, `TYPE`) VALUES (11, 'bucket-name', '云存储服务名称', 'huawei');
|
||||
INSERT INTO STORAGE_CONFIG (`ID`, `k`, `TITLE`, `TYPE`) VALUES (12, 'domain', '加速域名', 'huawei');
|
||||
INSERT INTO STORAGE_CONFIG (`ID`, `k`, `TITLE`, `TYPE`) VALUES (13, 'endPoint', '区域', 'huawei');
|
||||
INSERT INTO STORAGE_CONFIG (`ID`, `k`, `TITLE`, `TYPE`) VALUES (14, 'accessKey', 'AccessKey', 'aliyun');
|
||||
INSERT INTO STORAGE_CONFIG (`ID`, `k`, `TITLE`, `TYPE`) VALUES (15, 'secretKey', 'SecretKey', 'aliyun');
|
||||
INSERT INTO STORAGE_CONFIG (`ID`, `k`, `TITLE`, `TYPE`) VALUES (16, 'bucket-name', 'Bucket 名称', 'aliyun');
|
||||
INSERT INTO STORAGE_CONFIG (`ID`, `k`, `TITLE`, `TYPE`) VALUES (17, 'domain', 'Bucket 域名 / CDN 加速域名', 'aliyun');
|
||||
INSERT INTO STORAGE_CONFIG (`ID`, `k`, `TITLE`, `TYPE`) VALUES (18, 'endPoint', '区域', 'aliyun');
|
||||
INSERT INTO STORAGE_CONFIG (`ID`, `k`, `TITLE`, `TYPE`) VALUES (19, 'filePath', '文件路径', 'local');
|
||||
INSERT INTO STORAGE_CONFIG (`ID`, `k`, `TITLE`, `TYPE`) VALUES (20, 'host', '域名或IP', 'ftp');
|
||||
INSERT INTO STORAGE_CONFIG (`ID`, `k`, `TITLE`, `TYPE`) VALUES (21, 'port', '端口', 'ftp');
|
||||
INSERT INTO STORAGE_CONFIG (`ID`, `k`, `TITLE`, `TYPE`) VALUES (22, 'username', '用户名', 'ftp');
|
||||
INSERT INTO STORAGE_CONFIG (`ID`, `k`, `TITLE`, `TYPE`) VALUES (23, 'password', '密码', 'ftp');
|
||||
INSERT INTO STORAGE_CONFIG (`ID`, `k`, `TITLE`, `TYPE`) VALUES (24, 'domain', '加速域名', 'ftp');
|
||||
INSERT INTO STORAGE_CONFIG (`ID`, `k`, `TITLE`, `TYPE`) VALUES (25, 'secretId', 'SecretId', 'tencent');
|
||||
INSERT INTO STORAGE_CONFIG (`ID`, `k`, `TITLE`, `TYPE`) VALUES (26, 'secretKey', 'SecretKey', 'tencent');
|
||||
INSERT INTO STORAGE_CONFIG (`ID`, `k`, `TITLE`, `TYPE`) VALUES (27, 'bucket-name', '云存储服务名称', 'tencent');
|
||||
INSERT INTO STORAGE_CONFIG (`ID`, `k`, `TITLE`, `TYPE`) VALUES (28, 'domain', '加速域名', 'tencent');
|
||||
INSERT INTO STORAGE_CONFIG (`ID`, `k`, `TITLE`, `TYPE`) VALUES (29, 'endPoint', '区域', 'tencent');
|
||||
INSERT INTO STORAGE_CONFIG (`ID`, `k`, `TITLE`, `TYPE`) VALUES (30, 'accessKey', 'AccessKey', 'minio');
|
||||
INSERT INTO STORAGE_CONFIG (`ID`, `k`, `TITLE`, `TYPE`) VALUES (31, 'secretKey', 'SecretKey', 'minio');
|
||||
INSERT INTO STORAGE_CONFIG (`ID`, `k`, `TITLE`, `TYPE`) VALUES (32, 'endPoint', '服务地址', 'minio');
|
||||
INSERT INTO STORAGE_CONFIG (`ID`, `k`, `TITLE`, `TYPE`) VALUES (33, 'bucket-name', '存储空间名称', 'minio');
|
||||
INSERT INTO STORAGE_CONFIG (`ID`, `k`, `TITLE`, `TYPE`) VALUES (34, 'base-path', '基路径', 'upyun');
|
||||
INSERT INTO STORAGE_CONFIG (`ID`, `k`, `TITLE`, `TYPE`) VALUES (35, 'base-path', '基路径', 'minio');
|
||||
INSERT INTO STORAGE_CONFIG (`ID`, `k`, `TITLE`, `TYPE`) VALUES (36, 'base-path', '基路径', 'tencent');
|
||||
INSERT INTO STORAGE_CONFIG (`ID`, `k`, `TITLE`, `TYPE`) VALUES (37, 'endPoint', '区域', 'qiniu');
|
||||
INSERT INTO STORAGE_CONFIG (`ID`, `k`, `TITLE`, `TYPE`) VALUES (38, 'base-path', '基路径', 'qiniu');
|
||||
INSERT INTO STORAGE_CONFIG (`ID`, `k`, `TITLE`, `TYPE`) VALUES (39, 'base-path', '基路径', 'aliyun');
|
||||
INSERT INTO STORAGE_CONFIG (`ID`, `k`, `TITLE`, `TYPE`) VALUES (40, 'base-path', '基路径', 'huawei');
|
||||
INSERT INTO STORAGE_CONFIG (`ID`, `k`, `TITLE`, `TYPE`) VALUES (41, 'base-path', '基路径', 'ftp');
|
||||
INSERT INTO STORAGE_CONFIG (`ID`, `k`, `TITLE`, `TYPE`) VALUES (42, 'accessToken', '访问令牌', 'onedrive');
|
||||
INSERT INTO STORAGE_CONFIG (`ID`, `k`, `TITLE`, `TYPE`) VALUES (43, 'refreshToken', '刷新令牌', 'onedrive');
|
||||
INSERT INTO STORAGE_CONFIG (`ID`, `k`, `TITLE`, `TYPE`) VALUES (44, 'accessToken', '访问令牌', 'onedrive-china');
|
||||
INSERT INTO STORAGE_CONFIG (`ID`, `k`, `TITLE`, `TYPE`) VALUES (45, 'refreshToken', '刷新令牌', 'onedrive-china');
|
||||
INSERT INTO STORAGE_CONFIG (`ID`, `k`, `TITLE`, `TYPE`) VALUES (46, 'accessKey', 'AccessKey', 's3');
|
||||
INSERT INTO STORAGE_CONFIG (`ID`, `k`, `TITLE`, `TYPE`) VALUES (47, 'secretKey', 'SecretKey', 's3');
|
||||
INSERT INTO STORAGE_CONFIG (`ID`, `k`, `TITLE`, `TYPE`) VALUES (48, 'endPoint', '服务地址(EndPoint)', 's3');
|
||||
INSERT INTO STORAGE_CONFIG (`ID`, `k`, `TITLE`, `TYPE`) VALUES (49, 'bucket-name', '存储空间名称', 's3');
|
||||
INSERT INTO STORAGE_CONFIG (`ID`, `k`, `TITLE`, `TYPE`) VALUES (50, 'base-path', '基路径', 's3');
|
||||
INSERT INTO STORAGE_CONFIG (`ID`, `k`, `TITLE`, `TYPE`) VALUES (51, 'domain', '加速域名', 's3');
|
||||
INSERT INTO STORAGE_CONFIG (`ID`, `k`, `TITLE`, `TYPE`) VALUES (52, 'pathStyle', '域名风格', 's3');
|
||||
INSERT INTO STORAGE_CONFIG (`ID`, `k`, `TITLE`, `TYPE`) VALUES (53, 'isPrivate', '是否是私有空间', 's3');
|
||||
INSERT INTO STORAGE_CONFIG (`ID`, `k`, `TITLE`, `TYPE`) VALUES (54, 'base-path', '基路径', 'onedrive');
|
||||
INSERT INTO STORAGE_CONFIG (`ID`, `k`, `TITLE`, `TYPE`) VALUES (55, 'base-path', '基路径', 'onedrive-china');
|
||||
INSERT INTO STORAGE_CONFIG (`ID`, `k`, `TITLE`, `TYPE`) VALUES (56, 'bucket-name', '云存储服务名称', 'ufile');
|
||||
INSERT INTO STORAGE_CONFIG (`ID`, `k`, `TITLE`, `TYPE`) VALUES (57, 'username', '操作员名称', 'ufile');
|
||||
INSERT INTO STORAGE_CONFIG (`ID`, `k`, `TITLE`, `TYPE`) VALUES (58, 'password', '操作员密码', 'ufile');
|
||||
INSERT INTO STORAGE_CONFIG (`ID`, `k`, `TITLE`, `TYPE`) VALUES (59, 'domain', '加速域名', 'ufile');
|
||||
INSERT INTO STORAGE_CONFIG (`ID`, `k`, `TITLE`, `TYPE`) VALUES (60, 'base-path', '基路径', 'ufile');
|
||||
INSERT INTO STORAGE_CONFIG (`ID`, `k`, `TITLE`, `TYPE`) VALUES (61, 'isPrivate', '是否是私有空间', 'tencent');
|
||||
INSERT INTO STORAGE_CONFIG (`ID`, `k`, `TITLE`, `TYPE`) VALUES (62, 'isPrivate', '是否是私有空间', 'aliyun');
|
||||
INSERT INTO STORAGE_CONFIG (`ID`, `k`, `TITLE`, `TYPE`) VALUES (63, 'isPrivate', '是否是私有空间', 'huawei');
|
||||
INSERT INTO STORAGE_CONFIG (`ID`, `k`, `TITLE`, `TYPE`) VALUES (64, 'isPrivate', '是否是私有空间', 'minio');
|
||||
INSERT INTO STORAGE_CONFIG (`ID`, `k`, `TITLE`, `TYPE`) VALUES (65, 'isPrivate', '是否是私有空间', 'qiniu');
|
||||
|
||||
|
||||
INSERT INTO SYSTEM_CONFIG (`ID`, `k`, `REMARK`) VALUES (18, 'layout', '页面布局');
|
||||
@@ -0,0 +1 @@
|
||||
.el-menu[data-v-23e92c9f],.el-row[data-v-23e92c9f]{height:100vh}
|
||||
@@ -1 +0,0 @@
|
||||
.el-row[data-v-5289a8fc]{padding:20px}.el-form-item[data-v-5289a8fc]{margin-right:50px}.card-title[data-v-5289a8fc]{color:rgba(0,0,0,.45);font-size:14px}.card-content[data-v-5289a8fc]{color:rgba(0,0,0,.85);font-size:25px;line-height:30px}.card-title-button[data-v-5289a8fc]{float:right;padding:3px 0}.table-search-input[data-v-5289a8fc]{width:300px;float:right}
|
||||
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
|
||||
.zfile-header[data-v-69b2489f]{height:48px;line-height:48px!important;background:#fafafa;border-bottom:1px solid rgba(0,0,0,.05);padding-left:30px}.zfile-header .el-breadcrumb[data-v-69b2489f],.zfile-header .el-input[data-v-69b2489f]{line-height:48px}@media only screen and (max-width:767px){.hidden-xs-only{display:none!important}}@media only screen and (min-width:768px){.hidden-sm-and-up{display:none!important}}@media only screen and (min-width:768px) and (max-width:991px){.hidden-sm-only{display:none!important}}@media only screen and (max-width:991px){.hidden-sm-and-down{display:none!important}}@media only screen and (min-width:992px){.hidden-md-and-up{display:none!important}}@media only screen and (min-width:992px) and (max-width:1199px){.hidden-md-only{display:none!important}}@media only screen and (max-width:1199px){.hidden-md-and-down{display:none!important}}@media only screen and (min-width:1200px){.hidden-lg-and-up{display:none!important}}@media only screen and (min-width:1200px) and (max-width:1919px){.hidden-lg-only{display:none!important}}@media only screen and (max-width:1919px){.hidden-lg-and-down{display:none!important}}@media only screen and (min-width:1920px){.hidden-xl-only{display:none!important}}#List[data-v-360f2068]{overflow:hidden}.el-table[data-v-360f2068]{margin:20px 0 0 20px;padding-right:30px;overflow-y:hidden}.el-table[data-v-360f2068]:before{height:0}.el-table svg[data-v-360f2068]{font-size:18px;margin-right:15px}#ListTable[data-v-360f2068] .table-header-left{margin-left:38px}#ListTable[data-v-360f2068] tr{cursor:pointer}.el-scrollbar[data-v-360f2068] .el-scrollbar__wrap{overflow-x:hidden!important}#videoDialog[data-v-360f2068] .el-dialog__body{padding:10px 0 0 0}#List[data-v-360f2068] .el-dialog__header{text-align:center;margin-bottom:-10px;padding:5px 0 5px 0}#videoDialog[data-v-360f2068] .el-dialog__headerbtn{top:10px}#textDialog[data-v-360f2068] .el-dialog{margin-bottom:0}.v-contextmenu-item[data-v-360f2068] label{margin-left:10px}@media screen and (max-device-width:1920px){#videoDialog[data-v-360f2068] .el-dialog{margin-top:5vh!important;width:70%!important}}@media screen and (max-device-width:769px){#videoDialog[data-v-360f2068] .el-dialog{margin-top:10vh!important;width:90%!important}}.operator-btn[data-v-360f2068]{color:#1e9fff;margin-right:20px;font-size:16px}#app{font-family:Helvetica Neue,Helvetica,PingFang SC,Hiragino Sans GB,Microsoft YaHei,"\5FAE\8F6F\96C5\9ED1",Arial,sans-serif;font-size:16px;line-height:1.5;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;color:#2c3e50;overflow-x:hidden}body{margin:unset}.icon,body{overflow:hidden}.icon{width:1em;height:1em;vertical-align:-.15em;fill:currentColor}::-webkit-scrollbar{width:6px;height:8px;background:rgba(144,147,153,.3)}::-webkit-scrollbar-button:vertical{display:none}::-webkit-scrollbar-corner,::-webkit-scrollbar-track{background-color:#e2e2e2}::-webkit-scrollbar-thumb{border-radius:8px;background-color:#a6a6a6}::-webkit-scrollbar-thumb:vertical:hover{background-color:#7f7f7f}::-webkit-scrollbar-thumb:vertical:active{background-color:rgba(0,0,0,.38)}.center-box-card{width:1100px;margin:0 auto}.markdown-body{height:300px;overflow-y:auto;padding:0!important;min-width:100%!important}.alert{background-color:#f4f4f5;color:#909399;font-size:12px;margin:0 0 0;width:100%;padding:10px 16px;-webkit-box-sizing:border-box;box-sizing:border-box;border-radius:4px;position:relative;overflow:hidden;opacity:1;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-transition:opacity .2s;transition:opacity .2s}
|
||||
.zfile-header[data-v-5fca0787]{height:48px;line-height:48px!important;background:#fafafa;border-bottom:1px solid rgba(0,0,0,.05);padding-left:30px}.zfile-header .el-breadcrumb[data-v-5fca0787],.zfile-header .el-input[data-v-5fca0787]{line-height:48px}@media only screen and (max-width:767px){.hidden-xs-only{display:none!important}}@media only screen and (min-width:768px){.hidden-sm-and-up{display:none!important}}@media only screen and (min-width:768px) and (max-width:991px){.hidden-sm-only{display:none!important}}@media only screen and (max-width:991px){.hidden-sm-and-down{display:none!important}}@media only screen and (min-width:992px){.hidden-md-and-up{display:none!important}}@media only screen and (min-width:992px) and (max-width:1199px){.hidden-md-only{display:none!important}}@media only screen and (max-width:1199px){.hidden-md-and-down{display:none!important}}@media only screen and (min-width:1200px){.hidden-lg-and-up{display:none!important}}@media only screen and (min-width:1200px) and (max-width:1919px){.hidden-lg-only{display:none!important}}@media only screen and (max-width:1919px){.hidden-lg-and-down{display:none!important}}@media only screen and (min-width:1920px){.hidden-xl-only{display:none!important}}#List[data-v-2ebcb9db]{overflow:hidden}.el-table[data-v-2ebcb9db]{margin:20px 0 0 20px;padding-right:30px;overflow-y:hidden}.el-table[data-v-2ebcb9db]:before{height:0}.el-table svg[data-v-2ebcb9db]{font-size:18px;margin-right:15px}#ListTable[data-v-2ebcb9db] .table-header-left{margin-left:38px}#ListTable[data-v-2ebcb9db] tr{cursor:pointer}.el-scrollbar[data-v-2ebcb9db] .el-scrollbar__wrap{overflow-x:hidden!important}#videoDialog[data-v-2ebcb9db] .el-dialog__body{padding:10px 0 0 0}#List[data-v-2ebcb9db] .el-dialog__header{text-align:center;margin-bottom:-10px;padding:5px 0 5px 0}#videoDialog[data-v-2ebcb9db] .el-dialog__headerbtn{top:10px}#textDialog[data-v-2ebcb9db] .el-dialog{margin-bottom:0}.v-contextmenu-item[data-v-2ebcb9db] label{margin-left:10px}@media screen and (max-device-width:1920px){#videoDialog[data-v-2ebcb9db] .el-dialog{margin-top:5vh!important;width:70%!important}}@media screen and (max-device-width:769px){#videoDialog[data-v-2ebcb9db] .el-dialog{margin-top:10vh!important;width:90%!important}}.operator-btn[data-v-2ebcb9db]{color:#1e9fff;margin-right:20px;font-size:16px}#app{font-family:Helvetica Neue,Helvetica,PingFang SC,Hiragino Sans GB,Microsoft YaHei,"\5FAE\8F6F\96C5\9ED1",Arial,sans-serif;font-size:16px;line-height:1.5;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;color:#2c3e50;overflow-x:hidden}body{margin:unset}.icon,body{overflow:hidden}.icon{width:1em;height:1em;vertical-align:-.15em;fill:currentColor}::-webkit-scrollbar{width:6px;height:8px;background:rgba(144,147,153,.3)}::-webkit-scrollbar-button:vertical{display:none}::-webkit-scrollbar-corner,::-webkit-scrollbar-track{background-color:#e2e2e2}::-webkit-scrollbar-thumb{border-radius:8px;background-color:#a6a6a6}::-webkit-scrollbar-thumb:vertical:hover{background-color:#7f7f7f}::-webkit-scrollbar-thumb:vertical:active{background-color:rgba(0,0,0,.38)}.center-box-card{width:1100px;margin:0 auto}.markdown-body{height:300px;overflow-y:auto;padding:0!important;min-width:100%!important}.alert{background-color:#f4f4f5;color:#909399;font-size:12px;margin:0 0 0;width:100%;padding:10px 16px;-webkit-box-sizing:border-box;box-sizing:border-box;border-radius:4px;position:relative;overflow:hidden;opacity:1;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-transition:opacity .2s;transition:opacity .2s}
|
||||
@@ -0,0 +1 @@
|
||||
.box-card[data-v-1c272cd0]{padding-top:30px;padding-right:30px;margin:25vh auto;height:40vh;overflow-y:auto}.el-select[data-v-1c272cd0]{width:100%}.zfile-word-aux[data-v-1c272cd0]{margin-left:20px;color:#aaa}
|
||||
@@ -1 +0,0 @@
|
||||
#storageForm[data-v-24d679d0]{margin-left:20px}#storageForm[data-v-24d679d0] .el-select{width:100%}.zfile-word-aux[data-v-24d679d0]{margin-left:20px;color:#aaa}.el-tabs[data-v-0a248fe4]{display:block}
|
||||
@@ -1 +0,0 @@
|
||||
.el-menu[data-v-e36af7ca],.el-row[data-v-e36af7ca]{height:100vh}
|
||||
@@ -0,0 +1 @@
|
||||
.markdown-body[data-v-271433d0]{padding:20px!important}.scroll[data-v-271433d0]{height:100vh;overflow-y:auto}
|
||||
@@ -1 +0,0 @@
|
||||
.el-row[data-v-30de6894]{overflow-y:auto}#siteForm[data-v-30de6894]{margin-top:20px;margin-left:20px}#siteForm[data-v-30de6894] .el-select{width:70%}.zfile-word-aux[data-v-30de6894]{margin-left:20px;color:#aaa}
|
||||
@@ -1 +0,0 @@
|
||||
.markdown-body[data-v-1d926c65]{padding:20px!important}.scroll[data-v-1d926c65]{height:100vh;overflow-y:auto}
|
||||
@@ -1 +0,0 @@
|
||||
.box-card[data-v-7d75c59c]{padding-top:30px;padding-right:30px;margin:10vh auto;height:75vh;overflow-y:auto}.el-select[data-v-7d75c59c]{width:100%}.zfile-word-aux[data-v-7d75c59c]{margin-left:20px;color:#aaa}
|
||||
@@ -0,0 +1 @@
|
||||
.el-row[data-v-7b40e23a]{overflow-y:auto}#siteForm[data-v-7b40e23a]{margin-top:20px;margin-left:20px}#siteForm[data-v-7b40e23a] .el-select{width:70%}
|
||||
@@ -0,0 +1 @@
|
||||
.zfile-word-aux[data-v-23fc179f]{margin-left:20px;color:#aaa}
|
||||
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
|
||||
<!DOCTYPE html><html><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/chunk-049ad60c.8d1c3f59.css rel=prefetch><link href=/css/chunk-06f6e882.4c106b9d.css rel=prefetch><link href=/css/chunk-09797b6e.0e88456f.css rel=prefetch><link href=/css/chunk-0b11d68a.2bc89311.css rel=prefetch><link href=/css/chunk-1f0cfb2a.773f5ef1.css rel=prefetch><link href=/css/chunk-227db9c4.091f6ac0.css rel=prefetch><link href=/css/chunk-28547ac9.d30178ad.css rel=prefetch><link href=/css/chunk-361b31cc.434c5719.css rel=prefetch><link href=/css/chunk-548ba676.5c3079db.css rel=prefetch><link href=/css/chunk-5a048f62.71936c2b.css rel=prefetch><link href=/css/chunk-6b263e10.bc5fc5af.css rel=prefetch><link href=/css/chunk-718902cb.e55a2dd9.css rel=prefetch><link href=/css/chunk-c5bf65e6.accc08d6.css rel=prefetch><link href=/css/chunk-d1e104d6.ecae5695.css rel=prefetch><link href=/css/chunk-faa8fca8.bb4fd588.css rel=prefetch><link href=/js/chunk-049ad60c.0b1b3166.js rel=prefetch><link href=/js/chunk-06f6e882.fc195f68.js rel=prefetch><link href=/js/chunk-09797b6e.7b1e5e16.js rel=prefetch><link href=/js/chunk-0b11d68a.d20d6721.js rel=prefetch><link href=/js/chunk-1f0cfb2a.05b8606a.js rel=prefetch><link href=/js/chunk-227db9c4.0342e2c8.js rel=prefetch><link href=/js/chunk-28547ac9.89bfa8e0.js rel=prefetch><link href=/js/chunk-2d0a43df.0bb25464.js rel=prefetch><link href=/js/chunk-2d0e57ec.56324ec2.js rel=prefetch><link href=/js/chunk-361b31cc.ec6b72b5.js rel=prefetch><link href=/js/chunk-548ba676.7767e226.js rel=prefetch><link href=/js/chunk-5a048f62.c7a85d91.js rel=prefetch><link href=/js/chunk-6b263e10.fe00e76b.js rel=prefetch><link href=/js/chunk-718902cb.4d2eda07.js rel=prefetch><link href=/js/chunk-c5bf65e6.bbf03f50.js rel=prefetch><link href=/js/chunk-d1e104d6.5ae45d97.js rel=prefetch><link href=/js/chunk-faa8fca8.429fb078.js rel=prefetch><link href=/css/app.34f4cf05.css rel=preload as=style><link href=/css/chunk-vendors.4a45e43f.css rel=preload as=style><link href=/js/app.a82d704b.js rel=preload as=script><link href=/js/chunk-vendors.b5ddaa46.js rel=preload as=script><link href=/css/chunk-vendors.4a45e43f.css rel=stylesheet><link href=/css/app.34f4cf05.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.b5ddaa46.js></script><script src=/js/app.a82d704b.js></script></body></html>
|
||||
<!DOCTYPE html><html><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/chunk-02f22860.feb62c82.css rel=prefetch><link href=/css/chunk-049ad60c.8d1c3f59.css rel=prefetch><link href=/css/chunk-06f6e882.4c106b9d.css rel=prefetch><link href=/css/chunk-07a35882.0e88456f.css rel=prefetch><link href=/css/chunk-2136f455.1ba478f4.css rel=prefetch><link href=/css/chunk-227db9c4.091f6ac0.css rel=prefetch><link href=/css/chunk-24112b4d.6b5327df.css rel=prefetch><link href=/css/chunk-361b31cc.434c5719.css rel=prefetch><link href=/css/chunk-4c69887f.7aac81e0.css rel=prefetch><link href=/css/chunk-6a2760fc.50f63948.css rel=prefetch><link href=/css/chunk-cf5906ce.d5432c19.css rel=prefetch><link href=/css/chunk-d1e104d6.ecae5695.css rel=prefetch><link href=/css/chunk-f1b5112e.d30178ad.css rel=prefetch><link href=/css/chunk-fe33dfa2.734c6a88.css rel=prefetch><link href=/js/chunk-02f22860.1fa0c7f9.js rel=prefetch><link href=/js/chunk-049ad60c.0b1b3166.js rel=prefetch><link href=/js/chunk-06f6e882.fc195f68.js rel=prefetch><link href=/js/chunk-07a35882.781f33fb.js rel=prefetch><link href=/js/chunk-2136f455.e499e949.js rel=prefetch><link href=/js/chunk-227db9c4.0342e2c8.js rel=prefetch><link href=/js/chunk-24112b4d.4453c4ce.js rel=prefetch><link href=/js/chunk-2d0a43df.0bb25464.js rel=prefetch><link href=/js/chunk-2d0e57ec.56324ec2.js rel=prefetch><link href=/js/chunk-361b31cc.ec6b72b5.js rel=prefetch><link href=/js/chunk-4c69887f.a7bdc194.js rel=prefetch><link href=/js/chunk-6a2760fc.071a3677.js rel=prefetch><link href=/js/chunk-cf5906ce.6b80535b.js rel=prefetch><link href=/js/chunk-d1e104d6.5ae45d97.js rel=prefetch><link href=/js/chunk-f1b5112e.c2c62934.js rel=prefetch><link href=/js/chunk-fe33dfa2.d10222f1.js rel=prefetch><link href=/css/app.34f4cf05.css rel=preload as=style><link href=/css/chunk-vendors.1f2b3e18.css rel=preload as=style><link href=/js/app.09beb623.js rel=preload as=script><link href=/js/chunk-vendors.47b7f6a4.js rel=preload as=script><link href=/css/chunk-vendors.1f2b3e18.css rel=stylesheet><link href=/css/app.34f4cf05.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.47b7f6a4.js></script><script src=/js/app.09beb623.js></script></body></html>
|
||||
1
src/main/resources/static/js/app.09beb623.js
Normal file
1
src/main/resources/static/js/app.09beb623.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
1
src/main/resources/static/js/chunk-02f22860.1fa0c7f9.js
Normal file
1
src/main/resources/static/js/chunk-02f22860.1fa0c7f9.js
Normal file
@@ -0,0 +1 @@
|
||||
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-02f22860"],{2448:function(t,e,i){},"30d5":function(t,e,i){"use strict";var s=i("2448"),a=i.n(s);a.a},adf4:function(t,e,i){"use strict";i.r(e);var s=function(){var t=this,e=t.$createElement,i=t._self._c||e;return i("el-row",[i("el-col",{attrs:{span:3}},[i("el-menu",{staticClass:"el-menu-vertical-demo",attrs:{"default-active":"/admin"!==this.$route.path?this.$route.path:"/admin/site",router:!0}},[i("el-menu-item",{attrs:{index:"/admin/site"}},[i("i",{staticClass:"el-icon-setting"}),i("span",{attrs:{slot:"title"},slot:"title"},[t._v("基本设置")])]),i("el-menu-item",{attrs:{index:"/admin/drive-list"}},[i("i",{staticClass:"el-icon-folder-opened"}),i("span",{attrs:{slot:"title"},slot:"title"},[t._v("驱动器列表")])]),i("el-menu-item",{attrs:{index:"/admin/view"}},[i("i",{staticClass:"el-icon-view"}),i("span",{attrs:{slot:"title"},slot:"title"},[t._v("显示设置")])]),i("el-menu-item",{attrs:{index:"/admin/password"}},[i("i",{staticClass:"el-icon-key"}),i("span",{attrs:{slot:"title"},slot:"title"},[t._v("修改密码")])]),i("el-menu-item",{attrs:{index:"/admin/api"}},[i("i",{staticClass:"el-icon-document"}),i("span",{attrs:{slot:"title"},slot:"title"},[t._v("API 文档")])]),i("el-menu-item",{attrs:{index:"/admin/monitor"}},[i("i",{staticClass:"el-icon-monitor"}),i("span",{attrs:{slot:"title"},slot:"title"},[t._v("系统监控")])]),i("el-menu-item",{on:{click:t.click}},[i("i",{staticClass:"el-icon-s-home"}),i("span",{attrs:{slot:"title"},slot:"title"},[t._v("前往首页")])])],1)],1),i("el-col",{attrs:{span:16}},[i("keep-alive",{attrs:{exclude:"CacheManager,SiteSetting"}},[i("router-view")],1)],1)],1)},a=[],n={name:"Index",data:function(){return{active:"/admin/storage"}},methods:{click:function(){window.open("/","_blank")}}},l=n,o=(i("30d5"),i("2877")),c=Object(o["a"])(l,s,a,!1,null,"23e92c9f",null);e["default"]=c.exports}}]);
|
||||
92
src/main/resources/static/js/chunk-07a35882.781f33fb.js
Normal file
92
src/main/resources/static/js/chunk-07a35882.781f33fb.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
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user