mirror of
https://github.com/zfile-dev/zfile.git
synced 2025-04-19 05:34:52 +00:00
Compare commits
27 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
96ab8ff7dd | ||
|
|
8809aca170 | ||
|
|
97106383b6 | ||
|
|
208da95234 | ||
|
|
d4c843f5f5 | ||
|
|
d273fc9f12 | ||
|
|
0b4a38218c | ||
|
|
2f57c5b5cc | ||
|
|
610f68295f | ||
|
|
39ced8eb84 | ||
|
|
368b7a1df2 | ||
|
|
8e2107cd46 | ||
|
|
fa32a33371 | ||
|
|
59116a9414 | ||
|
|
b2c732a389 | ||
|
|
0e1ffef92b | ||
|
|
a5b19d3577 | ||
|
|
185c84dd79 | ||
|
|
d554dd298c | ||
|
|
aa6ecf0aaa | ||
|
|
83692718e3 | ||
|
|
030bd95941 | ||
|
|
8722d11ac3 | ||
|
|
0131ff02c0 | ||
|
|
2d115bf1c6 | ||
|
|
946113216d | ||
|
|
77b05c6dac |
2
API.md
2
API.md
@@ -145,7 +145,7 @@
|
||||
"msg": "操作成功",
|
||||
"code": 0,
|
||||
"data": {
|
||||
"header": null, # 头部文件名称
|
||||
"readme": null, # 文档文件名称
|
||||
"viewConfig": {
|
||||
"siteName": "站点名称", # 站点名称
|
||||
"infoEnable": false, # 是否开启右侧信息框
|
||||
|
||||
29
README.md
29
README.md
@@ -10,13 +10,14 @@
|
||||
前端基于 [h5ai](https://larsjung.de/h5ai/) 的原有功能使用 Vue 重新开发了一遍. 后端采用 SpringBoot, 数据库采用内嵌数据库.
|
||||
|
||||
预览地址: [https://zfile.jun6.net](https://zfile.jun6.net)
|
||||
文档地址: [http://docs.zhaojun.im/zfile](http://docs.zhaojun.im/zfile)
|
||||
|
||||
## 系统特色
|
||||
|
||||
* 内存缓存 (免安装)
|
||||
* 内存数据库 (免安装)
|
||||
* 个性化配置
|
||||
* 自定义目录的 header 说明文件
|
||||
* 自定义目录的 readme 说明文件
|
||||
* 自定义 JS, CSS
|
||||
* 文件夹密码
|
||||
* 支持在线浏览文本文件, 视频, 图片, 音乐. (支持 FLV 和 HLS)
|
||||
@@ -43,9 +44,9 @@ apt install -y openjdk-8-jre-headless unzip
|
||||
下载项目:
|
||||
|
||||
```bash
|
||||
wget -P ~ https://c.jun6.net/ZFILE/zfile-1.2.war
|
||||
wget -P ~ https://c.jun6.net/ZFILE/zfile-release.war
|
||||
cd ~
|
||||
mkdir zfile && unzip zfile-1.2.war -d zfile && rm -rf zfile-1.2.war
|
||||
mkdir zfile && unzip zfile-release.war -d zfile && rm -rf zfile-release.war
|
||||
chmod +x ~/zfile/bin/*.sh
|
||||
```
|
||||
|
||||
@@ -119,19 +120,27 @@ https://login.chinacloudapi.cn/common/oauth2/v2.0/authorize?client_id=4a72d927-1
|
||||
|
||||
默认 H2 数据库文件地址: `~/.zfile/db/`, `~` 表示用户目录, windows 为 `C:/Users/用户名/`, linux 为 `/home/用户名/`, root 用户为 `/root/`
|
||||
|
||||
### 头尾文件和加密文件
|
||||
### 文档文件和加密文件
|
||||
|
||||
- 目录头部显示文件名为 `header.md`
|
||||
- 目录文档显示文件名为 `readme.md`
|
||||
- 目录需要密码访问, 添加文件 `password.txt` (无法拦截此文件被下载, 但可以改名文件)
|
||||
|
||||
## TODO
|
||||
## 开发计划
|
||||
|
||||
- [x] API 支持 [点击查看文档](https://github.com/zhaojun1998/zfile/blob/master/API.md)
|
||||
- [x] 更方便的部署方式
|
||||
- [ ] 文本预览更换更好用的编辑器
|
||||
- [ ] 后台支持上传、编辑、删除等操作
|
||||
- [ ] WebDav 支持
|
||||
- [ ] Docker 支持
|
||||
- [ ] 新功能 - 后台支持上传、编辑、删除等操作
|
||||
- [ ] 新功能 - WebDav 支持
|
||||
- [ ] 新功能 - Docker 支持
|
||||
- [ ] 新功能 - 离线下载 (aria2)
|
||||
- [ ] 体验优化 - 文本预览更换 vscode 同款编辑器 monaco editor
|
||||
- [ ] 体验优化 - 忽略文件列表 (正则表达式)
|
||||
- [ ] 体验优化 - 自定义支持预览的文件后缀 (正则表达式)
|
||||
- [ ] 布局优化 - 底部增加固定栏, 用于填写备案信息, 友情链接等信息.
|
||||
- [ ] 布局优化 - 自定义操作按钮 (现为右键实现)
|
||||
- [ ] 后台优化 - 设置按照其功能进行分离
|
||||
- [ ] 架构调整 - 支持多存储策略
|
||||
- [ ] 体验优化 - 一键安装脚本
|
||||
|
||||
## 支持作者
|
||||
|
||||
|
||||
4
pom.xml
4
pom.xml
@@ -12,7 +12,7 @@
|
||||
|
||||
<groupId>im.zhaojun</groupId>
|
||||
<artifactId>zfile</artifactId>
|
||||
<version>1.2</version>
|
||||
<version>1.6</version>
|
||||
<name>zfile</name>
|
||||
<packaging>war</packaging>
|
||||
<description>一个在线的文件浏览系统</description>
|
||||
@@ -148,7 +148,7 @@
|
||||
<configuration>
|
||||
<jvms>
|
||||
<jvm>-server</jvm>
|
||||
<jvm>-Xmx512m</jvm>
|
||||
<jvm>-Xmx300m -Xmx100m</jvm>
|
||||
<jvm>-Djava.security.egd=file:/dev/./urandom</jvm>
|
||||
</jvms>
|
||||
</configuration>
|
||||
|
||||
@@ -1,15 +1,10 @@
|
||||
package im.zhaojun.common.config;
|
||||
|
||||
import im.zhaojun.common.model.StorageConfig;
|
||||
import im.zhaojun.common.model.constant.StorageConfigConstant;
|
||||
import im.zhaojun.common.model.enums.StorageTypeEnum;
|
||||
import im.zhaojun.common.service.AbstractFileService;
|
||||
import im.zhaojun.common.service.StorageConfigService;
|
||||
import im.zhaojun.common.service.SystemConfigService;
|
||||
import im.zhaojun.onedrive.china.service.OneDriveChinaService;
|
||||
import im.zhaojun.onedrive.china.service.OneDriveServiceChinaImpl;
|
||||
import im.zhaojun.onedrive.common.model.OneDriveToken;
|
||||
import im.zhaojun.onedrive.international.service.OneDriveService;
|
||||
import im.zhaojun.onedrive.china.service.OneDriveChinaServiceImpl;
|
||||
import im.zhaojun.onedrive.international.service.OneDriveServiceImpl;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
@@ -18,7 +13,6 @@ import org.springframework.scheduling.annotation.Scheduled;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
@@ -33,10 +27,10 @@ public class GlobalScheduleTask {
|
||||
private StorageConfigService storageConfigService;
|
||||
|
||||
@Resource
|
||||
private OneDriveService oneDriveService;
|
||||
private OneDriveServiceImpl oneDriveServiceImpl;
|
||||
|
||||
@Resource
|
||||
private OneDriveChinaService oneDriveChinaService;
|
||||
private OneDriveChinaServiceImpl oneDriveChinaServiceImpl;
|
||||
|
||||
@Resource
|
||||
private SystemConfigService systemConfigService;
|
||||
@@ -50,7 +44,7 @@ public class GlobalScheduleTask {
|
||||
AbstractFileService currentFileService = systemConfigService.getCurrentFileService();
|
||||
|
||||
if (!(currentFileService instanceof OneDriveServiceImpl
|
||||
|| currentFileService instanceof OneDriveServiceChinaImpl)) {
|
||||
|| currentFileService instanceof OneDriveChinaServiceImpl)) {
|
||||
log.debug("当前启用存储类型, 不是 OneDrive, 跳过自动刷新 AccessToken");
|
||||
return;
|
||||
}
|
||||
@@ -77,27 +71,11 @@ public class GlobalScheduleTask {
|
||||
* 调用刷新 OneDrive Token
|
||||
*/
|
||||
public void refreshOneDriveToken(StorageTypeEnum storageType) {
|
||||
|
||||
OneDriveToken refreshToken;
|
||||
if (Objects.equals(storageType, StorageTypeEnum.ONE_DRIVE_CHINA)) {
|
||||
refreshToken = oneDriveChinaService.getRefreshToken(storageType);
|
||||
oneDriveChinaServiceImpl.refreshOneDriveToken();
|
||||
} else {
|
||||
refreshToken = oneDriveService.getRefreshToken(storageType);
|
||||
oneDriveServiceImpl.refreshOneDriveToken();
|
||||
}
|
||||
|
||||
|
||||
if (refreshToken.getAccessToken() == null || refreshToken.getRefreshToken() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
StorageConfig accessTokenConfig =
|
||||
storageConfigService.selectByTypeAndKey(storageType, StorageConfigConstant.ACCESS_TOKEN_KEY);
|
||||
StorageConfig refreshTokenConfig =
|
||||
storageConfigService.selectByTypeAndKey(storageType, StorageConfigConstant.REFRESH_TOKEN_KEY);
|
||||
accessTokenConfig.setValue(refreshToken.getAccessToken());
|
||||
refreshTokenConfig.setValue(refreshToken.getRefreshToken());
|
||||
|
||||
storageConfigService.updateStorageConfig(Arrays.asList(accessTokenConfig, refreshTokenConfig));
|
||||
log.info("刷新 {} key 时间: {}", storageType.getDescription(), LocalDateTime.now());
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,9 @@
|
||||
package im.zhaojun.common.config;
|
||||
|
||||
import im.zhaojun.common.model.enums.StorageTypeEnumDeSerializerConvert;
|
||||
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
|
||||
import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.format.FormatterRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
@@ -15,4 +18,14 @@ public class WebMvcConfig implements WebMvcConfigurer {
|
||||
public void addFormatters(FormatterRegistry registry) {
|
||||
registry.addConverter(new StorageTypeEnumDeSerializerConvert());
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ServletWebServerFactory webServerFactory() {
|
||||
TomcatServletWebServerFactory webServerFactory = new TomcatServletWebServerFactory();
|
||||
webServerFactory.addConnectorCustomizers(connector -> {
|
||||
connector.setAttribute("relaxedPathChars", "<>[\\]^`{|}");
|
||||
connector.setAttribute("relaxedQueryChars", "<>[\\]^`{|}");
|
||||
});
|
||||
return webServerFactory;
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,8 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -72,7 +74,7 @@ public class FileController {
|
||||
|
||||
|
||||
/**
|
||||
* 获取系统配置信息和当前页的标题, 文件头, 文件尾信息
|
||||
* 获取系统配置信息和当前页的标题, 页面文档信息
|
||||
* @param path 路径
|
||||
*/
|
||||
@CheckStorageStrategyInit
|
||||
@@ -105,7 +107,7 @@ public class FileController {
|
||||
|
||||
|
||||
/**
|
||||
* 过滤文件列表, 不显示密码, 头部和尾部文件.
|
||||
* 过滤文件列表, 不显示密码, 文档文件.
|
||||
*/
|
||||
private void filterFileList(List<FileItemDTO> fileItemList) {
|
||||
if (fileItemList == null) {
|
||||
@@ -113,16 +115,19 @@ public class FileController {
|
||||
}
|
||||
|
||||
fileItemList.removeIf(fileItem -> ZFileConstant.PASSWORD_FILE_NAME.equals(fileItem.getName())
|
||||
|| ZFileConstant.HEADER_FILE_NAME.equals(fileItem.getName()));
|
||||
|| ZFileConstant.README_FILE_NAME.equals(fileItem.getName()));
|
||||
}
|
||||
|
||||
|
||||
private List<FileItemDTO> getSortedPagingData(List<FileItemDTO> fileItemList, Integer page) {
|
||||
// 排序, 先按照文件类型比较, 文件夹在前, 文件在后, 然后根据 sortBy 字段排序, 默认为升序;
|
||||
fileItemList.sort(new FileComparator());
|
||||
filterFileList(fileItemList);
|
||||
ArrayList<FileItemDTO> copy = new ArrayList<>(Arrays.asList(new FileItemDTO[fileItemList.size()]));
|
||||
Collections.copy(copy, fileItemList);
|
||||
|
||||
int total = fileItemList.size();
|
||||
// 排序, 先按照文件类型比较, 文件夹在前, 文件在后, 然后根据 sortBy 字段排序, 默认为升序;
|
||||
copy.sort(new FileComparator());
|
||||
filterFileList(copy);
|
||||
|
||||
int total = copy.size();
|
||||
int totalPage = (total + PAGE_SIZE - 1) / PAGE_SIZE;
|
||||
|
||||
if (page > totalPage) {
|
||||
@@ -132,7 +137,7 @@ public class FileController {
|
||||
int start = (page - 1) * PAGE_SIZE;
|
||||
int end = page * PAGE_SIZE;
|
||||
end = Math.min(end, total);
|
||||
return new ArrayList<>(fileItemList.subList(start, end));
|
||||
return new ArrayList<>(copy.subList(start, end));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
package im.zhaojun.common.controller;
|
||||
|
||||
import cn.hutool.core.util.URLUtil;
|
||||
import im.zhaojun.common.model.dto.FileItemDTO;
|
||||
import im.zhaojun.common.model.enums.FileTypeEnum;
|
||||
import im.zhaojun.common.service.AbstractFileService;
|
||||
import im.zhaojun.common.service.SystemConfigService;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.util.AntPathMatcher;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.servlet.HandlerMapping;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.net.MalformedURLException;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* @author Zhao Jun
|
||||
* 2020/2/9 11:17
|
||||
*/
|
||||
@Controller
|
||||
public class PageController {
|
||||
|
||||
@Resource
|
||||
private SystemConfigService systemConfigService;
|
||||
|
||||
@GetMapping("/directlink/**")
|
||||
public String directlink(final HttpServletRequest request) throws MalformedURLException {
|
||||
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);
|
||||
|
||||
if (filePath.length() > 0 && filePath.charAt(0) != '/') {
|
||||
filePath = "/" + filePath;
|
||||
}
|
||||
|
||||
AbstractFileService fileService = systemConfigService.getCurrentFileService();
|
||||
FileItemDTO fileItem = fileService.getFileItem(filePath);
|
||||
|
||||
String url = fileItem.getUrl();
|
||||
|
||||
int queryIndex = url.indexOf('?');
|
||||
|
||||
if (queryIndex != -1) {
|
||||
String origin = url.substring(0, queryIndex);
|
||||
String queryString = url.substring(queryIndex + 1);
|
||||
|
||||
url = URLUtil.encode(origin) + "?" + URLUtil.encode(queryString);
|
||||
} else {
|
||||
url = URLUtil.encode(url);
|
||||
}
|
||||
|
||||
|
||||
if (Objects.equals(fileItem.getType(), FileTypeEnum.FOLDER)) {
|
||||
return "redirect:" + fileItem.getUrl();
|
||||
} else {
|
||||
return "redirect:" + url;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -27,7 +27,7 @@ public class StorageConfig {
|
||||
|
||||
private String title;
|
||||
|
||||
@Column(length = 2048)
|
||||
@Column(length = 4000)
|
||||
private String value;
|
||||
|
||||
public Integer getId() {
|
||||
|
||||
@@ -15,9 +15,9 @@ public class ZFileConstant {
|
||||
public static final String AUDIO_TMP_PATH = "/.zfile/tmp/audio/";
|
||||
|
||||
/**
|
||||
* 页面头部文件
|
||||
* 页面文档文件
|
||||
*/
|
||||
public static String HEADER_FILE_NAME = "header.md";
|
||||
public static String README_FILE_NAME = "readme.md";
|
||||
|
||||
/**
|
||||
* 密码文件
|
||||
@@ -25,8 +25,8 @@ public class ZFileConstant {
|
||||
public static String PASSWORD_FILE_NAME = "password.txt";
|
||||
|
||||
@Autowired(required = false)
|
||||
public void setHeaderFileName(@Value("${zfile.constant.header}") String headerFileName) {
|
||||
ZFileConstant.HEADER_FILE_NAME = headerFileName;
|
||||
public void setHeaderFileName(@Value("${zfile.constant.readme}") String headerFileName) {
|
||||
ZFileConstant.README_FILE_NAME = headerFileName;
|
||||
}
|
||||
|
||||
@Autowired(required = false)
|
||||
|
||||
@@ -15,7 +15,7 @@ public class SiteConfigDTO implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 8811196207046121740L;
|
||||
|
||||
private String header;
|
||||
private String readme;
|
||||
|
||||
@JsonProperty("viewConfig")
|
||||
private SystemConfigDTO systemConfigDTO;
|
||||
|
||||
@@ -44,4 +44,15 @@ public class SystemConfigDTO {
|
||||
|
||||
private String customCss;
|
||||
|
||||
private String tableSize;
|
||||
|
||||
private Boolean showOperator;
|
||||
|
||||
private Boolean showDocument;
|
||||
|
||||
private String announcement;
|
||||
|
||||
private Boolean showAnnouncement;
|
||||
|
||||
private String layout;
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
package im.zhaojun.common.service;
|
||||
|
||||
import cn.hutool.core.util.BooleanUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.URLUtil;
|
||||
import com.amazonaws.services.s3.AmazonS3;
|
||||
import com.amazonaws.services.s3.model.ListObjectsRequest;
|
||||
@@ -112,11 +111,21 @@ public abstract class AbstractS3FileService extends AbstractFileService {
|
||||
|
||||
@Override
|
||||
public FileItemDTO getFileItem(String path) {
|
||||
List<FileItemDTO> list = fileList(path);
|
||||
|
||||
if (list == null || list.size() == 0) {
|
||||
List<FileItemDTO> list;
|
||||
try {
|
||||
int end = path.lastIndexOf("/");
|
||||
list = fileList(path.substring(0, end + 1));
|
||||
} catch (Exception e) {
|
||||
throw new NotExistFileException();
|
||||
}
|
||||
return list.get(0);
|
||||
|
||||
for (FileItemDTO fileItemDTO : list) {
|
||||
String fullPath = StringUtils.concatUrl(fileItemDTO.getPath(), fileItemDTO.getName());
|
||||
if (Objects.equals(fullPath, path)) {
|
||||
return fileItemDTO;
|
||||
}
|
||||
}
|
||||
|
||||
throw new NotExistFileException();
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,7 @@ public class SystemService {
|
||||
private SystemConfigService systemConfigService;
|
||||
|
||||
/**
|
||||
* 构建指定路径下标题, 页头, 页尾
|
||||
* 构建指定路径下标题, 页面文档信息
|
||||
* @param path 路径
|
||||
*/
|
||||
public synchronized SiteConfigDTO getConfig(String path) throws Exception {
|
||||
@@ -30,8 +30,8 @@ public class SystemService {
|
||||
|
||||
List<FileItemDTO> fileItemList = new ArrayList<>(fileService.fileList(path));
|
||||
for (FileItemDTO fileItemDTO : fileItemList) {
|
||||
if (ZFileConstant.HEADER_FILE_NAME.equalsIgnoreCase(fileItemDTO.getName())) {
|
||||
siteConfigDTO.setHeader(HttpUtil.getTextContent(fileItemDTO.getUrl()));
|
||||
if (ZFileConstant.README_FILE_NAME.equalsIgnoreCase(fileItemDTO.getName())) {
|
||||
siteConfigDTO.setReadme(HttpUtil.getTextContent(fileItemDTO.getUrl()));
|
||||
}
|
||||
}
|
||||
return siteConfigDTO;
|
||||
|
||||
@@ -37,16 +37,15 @@ public class FileComparator implements Comparator<FileItemDTO> {
|
||||
if (order == null) {
|
||||
order = "asc";
|
||||
}
|
||||
|
||||
FileTypeEnum o1Type = o1.getType();
|
||||
FileTypeEnum o2Type = o2.getType();
|
||||
|
||||
NaturalOrderComparator naturalOrderComparator = new NaturalOrderComparator();
|
||||
if (o1Type.equals(o2Type)) {
|
||||
int result;
|
||||
switch (sortBy) {
|
||||
case "time": result = o1.getTime().compareTo(o2.getTime()); break;
|
||||
case "size": result = o1.getSize().compareTo(o2.getSize()); break;
|
||||
default: result = o1.getName().compareToIgnoreCase(o2.getName()); break;
|
||||
default: result = naturalOrderComparator.compare(o1.getName(), o2.getName()); break;
|
||||
}
|
||||
return "asc".equals(order) ? result : -result;
|
||||
}
|
||||
@@ -57,4 +56,4 @@ public class FileComparator implements Comparator<FileItemDTO> {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
142
src/main/java/im/zhaojun/common/util/NaturalOrderComparator.java
Normal file
142
src/main/java/im/zhaojun/common/util/NaturalOrderComparator.java
Normal file
@@ -0,0 +1,142 @@
|
||||
package im.zhaojun.common.util;
|
||||
/*
|
||||
NaturalOrderComparator.java -- Perform 'natural order' comparisons of strings in Java.
|
||||
Copyright (C) 2003 by Pierre-Luc Paour <natorder@paour.com>
|
||||
|
||||
Based on the C version by Martin Pool, of which this is more or less a straight conversion.
|
||||
Copyright (C) 2000 by Martin Pool <mbp@humbug.org.au>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
public class NaturalOrderComparator implements Comparator<String> {
|
||||
|
||||
private int compareRight(String a, String b) {
|
||||
int bias = 0, ia = 0, ib = 0;
|
||||
|
||||
// The longest run of digits wins. That aside, the greatest
|
||||
// value wins, but we can't know that it will until we've scanned
|
||||
// both numbers to know that they have the same magnitude, so we
|
||||
// remember it in BIAS.
|
||||
for (; ; ia++, ib++) {
|
||||
char ca = charAt(a, ia);
|
||||
char cb = charAt(b, ib);
|
||||
|
||||
if (!isDigit(ca) && !isDigit(cb)) {
|
||||
return bias;
|
||||
}
|
||||
if (!isDigit(ca)) {
|
||||
return -1;
|
||||
}
|
||||
if (!isDigit(cb)) {
|
||||
return +1;
|
||||
}
|
||||
if (ca == 0 && cb == 0) {
|
||||
return bias;
|
||||
}
|
||||
|
||||
if (bias == 0) {
|
||||
if (ca < cb) {
|
||||
bias = -1;
|
||||
} else if (ca > cb) {
|
||||
bias = +1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int compare(String a, String b) {
|
||||
int ia = 0, ib = 0;
|
||||
int nza = 0, nzb = 0;
|
||||
char ca, cb;
|
||||
|
||||
while (true) {
|
||||
// Only count the number of zeroes leading the last number compared
|
||||
nza = nzb = 0;
|
||||
|
||||
ca = charAt(a, ia);
|
||||
cb = charAt(b, ib);
|
||||
|
||||
// skip over leading spaces or zeros
|
||||
while (Character.isSpaceChar(ca) || ca == '0') {
|
||||
if (ca == '0') {
|
||||
nza++;
|
||||
} else {
|
||||
// Only count consecutive zeroes
|
||||
nza = 0;
|
||||
}
|
||||
|
||||
ca = charAt(a, ++ia);
|
||||
}
|
||||
|
||||
while (Character.isSpaceChar(cb) || cb == '0') {
|
||||
if (cb == '0') {
|
||||
nzb++;
|
||||
} else {
|
||||
// Only count consecutive zeroes
|
||||
nzb = 0;
|
||||
}
|
||||
|
||||
cb = charAt(b, ++ib);
|
||||
}
|
||||
|
||||
// Process run of digits
|
||||
if (Character.isDigit(ca) && Character.isDigit(cb)) {
|
||||
int bias = compareRight(a.substring(ia), b.substring(ib));
|
||||
if (bias != 0) {
|
||||
return bias;
|
||||
}
|
||||
}
|
||||
|
||||
if (ca == 0 && cb == 0) {
|
||||
// The strings compare the same. Perhaps the caller
|
||||
// will want to call strcmp to break the tie.
|
||||
return compareEqual(a, b, nza, nzb);
|
||||
}
|
||||
if (ca < cb) {
|
||||
return -1;
|
||||
}
|
||||
if (ca > cb) {
|
||||
return +1;
|
||||
}
|
||||
|
||||
++ia;
|
||||
++ib;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isDigit(char c) {
|
||||
return Character.isDigit(c) || c == '.' || c == ',';
|
||||
}
|
||||
|
||||
private static char charAt(String s, int i) {
|
||||
return i >= s.length() ? 0 : s.charAt(i);
|
||||
}
|
||||
|
||||
private static int compareEqual(String a, String b, int nza, int nzb) {
|
||||
if (nza - nzb != 0)
|
||||
return nza - nzb;
|
||||
|
||||
if (a.length() == b.length())
|
||||
return a.compareTo(b);
|
||||
|
||||
return a.length() - b.length();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
package im.zhaojun.local.controller;
|
||||
|
||||
import cn.hutool.core.util.URLUtil;
|
||||
import im.zhaojun.common.exception.NotExistFileException;
|
||||
import im.zhaojun.common.util.StringUtils;
|
||||
import im.zhaojun.local.service.LocalServiceImpl;
|
||||
import org.springframework.core.io.FileSystemResource;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Controller;
|
||||
@@ -30,20 +30,20 @@ public class LocalController {
|
||||
|
||||
@GetMapping("/file/**")
|
||||
@ResponseBody
|
||||
public ResponseEntity<FileSystemResource> downAttachment(final HttpServletRequest request) {
|
||||
public ResponseEntity<Object> downAttachment(final HttpServletRequest request) {
|
||||
String path = (String) request.getAttribute(
|
||||
HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE);
|
||||
String bestMatchPattern = (String) request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE);
|
||||
AntPathMatcher apm = new AntPathMatcher();
|
||||
String filePath = apm.extractPathWithinPattern(bestMatchPattern, path);
|
||||
|
||||
return export(new File(StringUtils.concatPath(localServiceImpl.getFilePath(), URLUtil.decode(filePath))));
|
||||
return export(new File(StringUtils.concatPath(localServiceImpl.getFilePath(), filePath)));
|
||||
}
|
||||
|
||||
private ResponseEntity<FileSystemResource> export(File file) {
|
||||
private ResponseEntity<Object> export(File file) {
|
||||
|
||||
if (!file.exists()) {
|
||||
throw new NotExistFileException();
|
||||
return ResponseEntity.status(HttpStatus.NOT_FOUND).body("404 FILE NOT FOUND");
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -90,7 +90,7 @@ public class LocalServiceImpl extends AbstractFileService implements FileService
|
||||
@Override
|
||||
public String getDownloadUrl(String path) {
|
||||
SystemConfig usernameConfig = systemConfigRepository.findByKey(SystemConfigConstant.DOMAIN);
|
||||
return URLUtil.encode(StringUtils.removeDuplicateSeparator(usernameConfig.getValue() + "/file/" + path));
|
||||
return StringUtils.removeDuplicateSeparator(usernameConfig.getValue() + "/file/" + path);
|
||||
}
|
||||
|
||||
public String getFilePath() {
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
package im.zhaojun.onedrive.china.service;
|
||||
|
||||
import im.zhaojun.onedrive.common.service.AbstractOneDriveService;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Service
|
||||
public class OneDriveChinaService extends AbstractOneDriveService {
|
||||
|
||||
@Value("${zfile.onedirve-china.clientId}")
|
||||
private String clientId;
|
||||
|
||||
@Value("${zfile.onedirve-china.redirectUri}")
|
||||
private String redirectUri;
|
||||
|
||||
@Value("${zfile.onedirve-china.clientSecret}")
|
||||
private String clientSecret;
|
||||
|
||||
@Value("${zfile.onedirve-china.scope}")
|
||||
private String scope;
|
||||
|
||||
@Override
|
||||
public String getGraphEndPoint() {
|
||||
return "microsoftgraph.chinacloudapi.cn";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAuthenticateEndPoint() {
|
||||
return "login.partner.microsoftonline.cn";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getClientId() {
|
||||
return clientId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRedirectUri() {
|
||||
return redirectUri;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getClientSecret() {
|
||||
return clientSecret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getScope() {
|
||||
return scope;
|
||||
}
|
||||
}
|
||||
@@ -1,20 +1,18 @@
|
||||
package im.zhaojun.onedrive.china.service;
|
||||
|
||||
import im.zhaojun.common.config.GlobalScheduleTask;
|
||||
import im.zhaojun.common.exception.NotExistFileException;
|
||||
import im.zhaojun.common.model.StorageConfig;
|
||||
import im.zhaojun.common.model.constant.StorageConfigConstant;
|
||||
import im.zhaojun.common.model.dto.FileItemDTO;
|
||||
import im.zhaojun.common.model.enums.StorageTypeEnum;
|
||||
import im.zhaojun.common.service.AbstractFileService;
|
||||
import im.zhaojun.common.service.FileService;
|
||||
import im.zhaojun.common.service.StorageConfigService;
|
||||
import im.zhaojun.onedrive.common.service.AbstractOneDriveService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
@@ -22,7 +20,7 @@ import java.util.Map;
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class OneDriveServiceChinaImpl extends AbstractFileService implements FileService {
|
||||
public class OneDriveChinaServiceImpl extends AbstractOneDriveService implements FileService {
|
||||
|
||||
@Resource
|
||||
private GlobalScheduleTask globalScheduleTask;
|
||||
@@ -30,8 +28,17 @@ public class OneDriveServiceChinaImpl extends AbstractFileService implements Fil
|
||||
@Resource
|
||||
private StorageConfigService storageConfigService;
|
||||
|
||||
@Resource
|
||||
private OneDriveChinaService oneDriveChinaService;
|
||||
@Value("${zfile.onedirve-china.clientId}")
|
||||
private String clientId;
|
||||
|
||||
@Value("${zfile.onedirve-china.redirectUri}")
|
||||
private String redirectUri;
|
||||
|
||||
@Value("${zfile.onedirve-china.clientSecret}")
|
||||
private String clientSecret;
|
||||
|
||||
@Value("${zfile.onedirve-china.scope}")
|
||||
private String scope;
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
@@ -46,7 +53,7 @@ public class OneDriveServiceChinaImpl extends AbstractFileService implements Fil
|
||||
log.debug("初始化存储策略 [{}] 失败: 参数不完整", getStorageTypeEnum().getDescription());
|
||||
isInitialized = false;
|
||||
} else {
|
||||
globalScheduleTask.refreshOneDriveToken(getStorageTypeEnum());
|
||||
refreshOneDriveToken();
|
||||
isInitialized = testConnection();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
@@ -54,11 +61,6 @@ public class OneDriveServiceChinaImpl extends AbstractFileService implements Fil
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FileItemDTO> fileList(String path) {
|
||||
return oneDriveChinaService.list(basePath, path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDownloadUrl(String path) {
|
||||
return null;
|
||||
@@ -70,14 +72,32 @@ public class OneDriveServiceChinaImpl extends AbstractFileService implements Fil
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileItemDTO getFileItem(String path) {
|
||||
FileItemDTO fileItemDTO ;
|
||||
public String getGraphEndPoint() {
|
||||
return "microsoftgraph.chinacloudapi.cn";
|
||||
}
|
||||
|
||||
try {
|
||||
fileItemDTO = oneDriveChinaService.getItem(path);
|
||||
} catch (Exception e) {
|
||||
throw new NotExistFileException();
|
||||
}
|
||||
return fileItemDTO;
|
||||
@Override
|
||||
public String getAuthenticateEndPoint() {
|
||||
return "login.partner.microsoftonline.cn";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getClientId() {
|
||||
return clientId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRedirectUri() {
|
||||
return redirectUri;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getClientSecret() {
|
||||
return clientSecret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getScope() {
|
||||
return scope;
|
||||
}
|
||||
}
|
||||
@@ -4,8 +4,8 @@ import im.zhaojun.common.model.StorageConfig;
|
||||
import im.zhaojun.common.model.constant.StorageConfigConstant;
|
||||
import im.zhaojun.common.model.enums.StorageTypeEnum;
|
||||
import im.zhaojun.common.service.StorageConfigService;
|
||||
import im.zhaojun.onedrive.china.service.OneDriveChinaService;
|
||||
import im.zhaojun.onedrive.international.service.OneDriveService;
|
||||
import im.zhaojun.onedrive.china.service.OneDriveChinaServiceImpl;
|
||||
import im.zhaojun.onedrive.international.service.OneDriveServiceImpl;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
@@ -26,11 +26,11 @@ public class OneDriveConfig {
|
||||
|
||||
@Resource
|
||||
@Lazy
|
||||
private OneDriveService oneDriveService;
|
||||
private OneDriveServiceImpl oneDriveServiceImpl;
|
||||
|
||||
@Resource
|
||||
@Lazy
|
||||
private OneDriveChinaService oneDriveChinaService;
|
||||
private OneDriveChinaServiceImpl oneDriveChinaServiceImpl;
|
||||
|
||||
@Bean
|
||||
public RestTemplate oneDriveRestTemplate() {
|
||||
@@ -39,9 +39,9 @@ public class OneDriveConfig {
|
||||
ClientHttpRequestInterceptor interceptor = (httpRequest, bytes, clientHttpRequestExecution) -> {
|
||||
String host = httpRequest.getURI().getHost();
|
||||
StorageTypeEnum type;
|
||||
if (oneDriveChinaService.getGraphEndPoint().contains(host)) {
|
||||
if (oneDriveChinaServiceImpl.getGraphEndPoint().contains(host)) {
|
||||
type = StorageTypeEnum.ONE_DRIVE_CHINA;
|
||||
} else if (oneDriveService.getGraphEndPoint().contains(host)) {
|
||||
} else if (oneDriveServiceImpl.getGraphEndPoint().contains(host)) {
|
||||
type = StorageTypeEnum.ONE_DRIVE;
|
||||
} else {
|
||||
return clientHttpRequestExecution.execute(httpRequest, bytes);
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package im.zhaojun.onedrive.common.controller;
|
||||
|
||||
import im.zhaojun.onedrive.china.service.OneDriveChinaService;
|
||||
import im.zhaojun.onedrive.china.service.OneDriveChinaServiceImpl;
|
||||
import im.zhaojun.onedrive.common.model.OneDriveToken;
|
||||
import im.zhaojun.onedrive.international.service.OneDriveService;
|
||||
import im.zhaojun.onedrive.international.service.OneDriveServiceImpl;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
@@ -18,14 +18,14 @@ import javax.annotation.Resource;
|
||||
public class OneDriveController {
|
||||
|
||||
@Resource
|
||||
private OneDriveService oneDriveService;
|
||||
private OneDriveServiceImpl oneDriveServiceImpl;
|
||||
|
||||
@Resource
|
||||
private OneDriveChinaService oneDriveChinaService;
|
||||
private OneDriveChinaServiceImpl oneDriveChinaServiceImpl;
|
||||
|
||||
@GetMapping("/callback")
|
||||
public String onedriveCallback(String code, Model model) {
|
||||
OneDriveToken oneDriveToken = oneDriveService.getToken(code);
|
||||
OneDriveToken oneDriveToken = oneDriveServiceImpl.getToken(code);
|
||||
model.addAttribute("accessToken", oneDriveToken.getAccessToken());
|
||||
model.addAttribute("refreshToken", oneDriveToken.getRefreshToken());
|
||||
return "callback";
|
||||
@@ -34,7 +34,7 @@ public class OneDriveController {
|
||||
|
||||
@GetMapping("/china-callback")
|
||||
public String onedriveChinaCallback(String code, Model model) {
|
||||
OneDriveToken oneDriveToken = oneDriveChinaService.getToken(code);
|
||||
OneDriveToken oneDriveToken = oneDriveChinaServiceImpl.getToken(code);
|
||||
model.addAttribute("accessToken", oneDriveToken.getAccessToken());
|
||||
model.addAttribute("refreshToken", oneDriveToken.getRefreshToken());
|
||||
return "callback";
|
||||
|
||||
@@ -11,8 +11,9 @@ import im.zhaojun.common.model.StorageConfig;
|
||||
import im.zhaojun.common.model.constant.StorageConfigConstant;
|
||||
import im.zhaojun.common.model.dto.FileItemDTO;
|
||||
import im.zhaojun.common.model.enums.FileTypeEnum;
|
||||
import im.zhaojun.common.model.enums.StorageTypeEnum;
|
||||
import im.zhaojun.common.repository.StorageConfigRepository;
|
||||
import im.zhaojun.common.service.AbstractFileService;
|
||||
import im.zhaojun.common.service.StorageConfigService;
|
||||
import im.zhaojun.common.util.StringUtils;
|
||||
import im.zhaojun.onedrive.common.model.OneDriveToken;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
@@ -20,14 +21,16 @@ import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.net.URLDecoder;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Zhao Jun
|
||||
* 2020/1/29 11:54
|
||||
*/
|
||||
public abstract class AbstractOneDriveService {
|
||||
public abstract class AbstractOneDriveService extends AbstractFileService {
|
||||
|
||||
protected static final String DRIVER_INFO_URL = "https://{graphEndPoint}/v1.0/me/drives";
|
||||
|
||||
@@ -45,9 +48,12 @@ public abstract class AbstractOneDriveService {
|
||||
@Resource
|
||||
private StorageConfigRepository storageConfigRepository;
|
||||
|
||||
public OneDriveToken getRefreshToken(StorageTypeEnum storageType) {
|
||||
@Resource
|
||||
private StorageConfigService storageConfigService;
|
||||
|
||||
public OneDriveToken getRefreshToken() {
|
||||
StorageConfig refreshStorageConfig =
|
||||
storageConfigRepository.findByTypeAndKey(storageType, StorageConfigConstant.REFRESH_TOKEN_KEY);
|
||||
storageConfigRepository.findByTypeAndKey(this.getStorageTypeEnum(), StorageConfigConstant.REFRESH_TOKEN_KEY);
|
||||
|
||||
String param = "client_id=" + getClientId() +
|
||||
"&redirect_uri=" + getRedirectUri() +
|
||||
@@ -79,13 +85,12 @@ public abstract class AbstractOneDriveService {
|
||||
return JSONObject.parseObject(response.body(), OneDriveToken.class);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public String getUserInfo() {
|
||||
return oneDriveRestTemplate.getForObject(DRIVER_INFO_URL, String.class);
|
||||
}
|
||||
|
||||
public List<FileItemDTO> list(String basePath, String path) {
|
||||
@Override
|
||||
public List<FileItemDTO> fileList(String path) {
|
||||
path = StringUtils.removeFirstSeparator(path);
|
||||
String fullPath = StringUtils.getFullPath(basePath, path);
|
||||
|
||||
@@ -97,6 +102,7 @@ public abstract class AbstractOneDriveService {
|
||||
String requestUrl;
|
||||
|
||||
if (nextLink != null) {
|
||||
nextLink = nextLink.replace("+", "%2B");
|
||||
requestUrl = URLUtil.decode(nextLink);
|
||||
}else if ("/".equalsIgnoreCase(fullPath) || "".equalsIgnoreCase(fullPath)) {
|
||||
requestUrl = DRIVER_ROOT_URL;
|
||||
@@ -137,11 +143,14 @@ public abstract class AbstractOneDriveService {
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileItemDTO getFileItem(String path) {
|
||||
|
||||
String fullPath = StringUtils.getFullPath(basePath, path);
|
||||
|
||||
public FileItemDTO getItem(String path) {
|
||||
String requestUrl;
|
||||
|
||||
ResponseEntity<String> responseEntity = oneDriveRestTemplate.getForEntity(DRIVER_ITEM_URL, String.class, path);
|
||||
ResponseEntity<String> responseEntity = oneDriveRestTemplate.getForEntity(DRIVER_ITEM_URL, String.class, getGraphEndPoint(), fullPath);
|
||||
String body = responseEntity.getBody();
|
||||
|
||||
JSONObject fileItem = JSON.parseObject(body);
|
||||
@@ -174,4 +183,21 @@ public abstract class AbstractOneDriveService {
|
||||
public abstract String getClientSecret();
|
||||
|
||||
public abstract String getScope();
|
||||
|
||||
public void refreshOneDriveToken() {
|
||||
OneDriveToken refreshToken = getRefreshToken();
|
||||
|
||||
if (refreshToken.getAccessToken() == null || refreshToken.getRefreshToken() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
StorageConfig accessTokenConfig =
|
||||
storageConfigService.selectByTypeAndKey(this.getStorageTypeEnum(), StorageConfigConstant.ACCESS_TOKEN_KEY);
|
||||
StorageConfig refreshTokenConfig =
|
||||
storageConfigService.selectByTypeAndKey(this.getStorageTypeEnum(), StorageConfigConstant.REFRESH_TOKEN_KEY);
|
||||
accessTokenConfig.setValue(refreshToken.getAccessToken());
|
||||
refreshTokenConfig.setValue(refreshToken.getRefreshToken());
|
||||
|
||||
storageConfigService.updateStorageConfig(Arrays.asList(accessTokenConfig, refreshTokenConfig));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
package im.zhaojun.onedrive.international.service;
|
||||
|
||||
import im.zhaojun.onedrive.common.service.AbstractOneDriveService;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Service
|
||||
public class OneDriveService extends AbstractOneDriveService {
|
||||
|
||||
@Value("${zfile.onedirve.clientId}")
|
||||
protected String clientId;
|
||||
|
||||
@Value("${zfile.onedirve.redirectUri}")
|
||||
protected String redirectUri;
|
||||
|
||||
@Value("${zfile.onedirve.clientSecret}")
|
||||
protected String clientSecret;
|
||||
|
||||
@Value("${zfile.onedirve.scope}")
|
||||
protected String scope;
|
||||
|
||||
@Override
|
||||
public String getGraphEndPoint() {
|
||||
return "graph.microsoft.com";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAuthenticateEndPoint() {
|
||||
return "login.microsoftonline.com";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getClientId() {
|
||||
return clientId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRedirectUri() {
|
||||
return redirectUri;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getClientSecret() {
|
||||
return clientSecret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getScope() {
|
||||
return scope;
|
||||
}
|
||||
}
|
||||
@@ -1,20 +1,18 @@
|
||||
package im.zhaojun.onedrive.international.service;
|
||||
|
||||
import im.zhaojun.common.config.GlobalScheduleTask;
|
||||
import im.zhaojun.common.exception.NotExistFileException;
|
||||
import im.zhaojun.common.model.StorageConfig;
|
||||
import im.zhaojun.common.model.constant.StorageConfigConstant;
|
||||
import im.zhaojun.common.model.dto.FileItemDTO;
|
||||
import im.zhaojun.common.model.enums.StorageTypeEnum;
|
||||
import im.zhaojun.common.service.AbstractFileService;
|
||||
import im.zhaojun.common.service.FileService;
|
||||
import im.zhaojun.common.service.StorageConfigService;
|
||||
import im.zhaojun.onedrive.common.service.AbstractOneDriveService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
@@ -22,7 +20,7 @@ import java.util.Map;
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class OneDriveServiceImpl extends AbstractFileService implements FileService {
|
||||
public class OneDriveServiceImpl extends AbstractOneDriveService implements FileService {
|
||||
|
||||
@Resource
|
||||
private GlobalScheduleTask globalScheduleTask;
|
||||
@@ -30,8 +28,17 @@ public class OneDriveServiceImpl extends AbstractFileService implements FileServ
|
||||
@Resource
|
||||
private StorageConfigService storageConfigService;
|
||||
|
||||
@Resource
|
||||
private OneDriveService oneDriveService;
|
||||
@Value("${zfile.onedirve.clientId}")
|
||||
protected String clientId;
|
||||
|
||||
@Value("${zfile.onedirve.redirectUri}")
|
||||
protected String redirectUri;
|
||||
|
||||
@Value("${zfile.onedirve.clientSecret}")
|
||||
protected String clientSecret;
|
||||
|
||||
@Value("${zfile.onedirve.scope}")
|
||||
protected String scope;
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
@@ -46,7 +53,7 @@ public class OneDriveServiceImpl extends AbstractFileService implements FileServ
|
||||
log.debug("初始化存储策略 [{}] 失败: 参数不完整", getStorageTypeEnum().getDescription());
|
||||
isInitialized = false;
|
||||
} else {
|
||||
globalScheduleTask.refreshOneDriveToken(getStorageTypeEnum());
|
||||
refreshOneDriveToken();
|
||||
isInitialized = testConnection();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
@@ -54,11 +61,6 @@ public class OneDriveServiceImpl extends AbstractFileService implements FileServ
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FileItemDTO> fileList(String path) {
|
||||
return oneDriveService.list(basePath, path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDownloadUrl(String path) {
|
||||
return null;
|
||||
@@ -70,14 +72,32 @@ public class OneDriveServiceImpl extends AbstractFileService implements FileServ
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileItemDTO getFileItem(String path) {
|
||||
FileItemDTO fileItemDTO ;
|
||||
|
||||
try {
|
||||
fileItemDTO = oneDriveService.getItem(path);
|
||||
} catch (Exception e) {
|
||||
throw new NotExistFileException();
|
||||
}
|
||||
return fileItemDTO;
|
||||
public String getGraphEndPoint() {
|
||||
return "graph.microsoft.com";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAuthenticateEndPoint() {
|
||||
return "login.microsoftonline.com";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getClientId() {
|
||||
return clientId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRedirectUri() {
|
||||
return redirectUri;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getClientSecret() {
|
||||
return clientSecret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getScope() {
|
||||
return scope;
|
||||
}
|
||||
}
|
||||
@@ -6,10 +6,10 @@
|
||||
"description": "目录缓存过期时间 和 下载地址过期时间. 单位为秒."
|
||||
},
|
||||
{
|
||||
"name": "zfile.constant.header",
|
||||
"name": "zfile.constant.readme",
|
||||
"type": "java.lang.String",
|
||||
"defaultValue": "header.md",
|
||||
"description": "头部文件 文件名."
|
||||
"defaultValue": "readme.md",
|
||||
"description": "文档文件 文件名."
|
||||
},
|
||||
{
|
||||
"name": "zfile.constant.password",
|
||||
|
||||
@@ -17,6 +17,8 @@ spring:
|
||||
datasource:
|
||||
# 初始化数据导入
|
||||
data: classpath*:db/data.sql
|
||||
sql-script-encoding: utf-8
|
||||
|
||||
initialization-mode: always
|
||||
continue-on-error: true
|
||||
|
||||
@@ -27,7 +29,7 @@ spring:
|
||||
password: 123456
|
||||
|
||||
# MySQL 配置
|
||||
# driver-class-name: com.mysql.jdbc.Driver
|
||||
# driver-class-name: com.mysql.jdbc.Driver
|
||||
# url: jdbc:mysql://127.0.0.1:3306/zfile?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false
|
||||
# username: root
|
||||
# password: 123456
|
||||
@@ -46,11 +48,15 @@ spring:
|
||||
gzipped: true
|
||||
profiles:
|
||||
active: prod
|
||||
|
||||
boot:
|
||||
admin:
|
||||
context-path: /act
|
||||
zfile:
|
||||
cache:
|
||||
timeout: 300
|
||||
constant:
|
||||
header: header.md
|
||||
readme: readme.md
|
||||
password: password.txt
|
||||
onedirve:
|
||||
clientId: 09939809-c617-43c8-a220-a93c1513c5d4
|
||||
@@ -69,4 +75,7 @@ jetcache:
|
||||
local:
|
||||
default:
|
||||
type: caffeine
|
||||
keyConvertor: fastjson
|
||||
keyConvertor: fastjson
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -10,6 +10,12 @@ 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', '表格大小');
|
||||
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');
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
.el-menu[data-v-d26ac70e],.el-row[data-v-d26ac70e]{height:100vh}
|
||||
1
src/main/resources/static/css/adminIndex.a8c53261.css
Normal file
1
src/main/resources/static/css/adminIndex.a8c53261.css
Normal file
@@ -0,0 +1 @@
|
||||
.el-menu[data-v-7f233ce7],.el-row[data-v-7f233ce7]{height:100vh}
|
||||
File diff suppressed because one or more lines are too long
1
src/main/resources/static/css/app.fffbf4d6.css
Normal file
1
src/main/resources/static/css/app.fffbf4d6.css
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1
src/main/resources/static/css/chunk-vendors.cb63319e.css
Normal file
1
src/main/resources/static/css/chunk-vendors.cb63319e.css
Normal file
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
|
||||
<!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1"><link rel=icon href=/favicon.ico><title></title><link href=/css/adminIndex.9c87dd59.css rel=prefetch><link href=/css/install.b4e8b552.css rel=prefetch><link href=/js/adminIndex.f735b8ee.js rel=prefetch><link href=/js/dplayer.acc587f7.js rel=prefetch><link href=/js/install.6a075002.js rel=prefetch><link href=/css/app.a2e3ef88.css rel=preload as=style><link href=/css/chunk-vendors.6ed6dc12.css rel=preload as=style><link href=/js/app.9d145c66.js rel=preload as=script><link href=/js/chunk-vendors.1f42ad6f.js rel=preload as=script><link href=/css/chunk-vendors.6ed6dc12.css rel=stylesheet><link href=/css/app.a2e3ef88.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.1f42ad6f.js></script><script src=/js/app.9d145c66.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/adminIndex.a8c53261.css rel=prefetch><link href=/css/install.b4e8b552.css rel=prefetch><link href=/js/adminIndex.0916d17e.js rel=prefetch><link href=/js/dplayer.acc587f7.js rel=prefetch><link href=/js/install.0f6d1155.js rel=prefetch><link href=/css/app.fffbf4d6.css rel=preload as=style><link href=/css/chunk-vendors.cb63319e.css rel=preload as=style><link href=/js/app.b328f663.js rel=preload as=script><link href=/js/chunk-vendors.d1dab075.js rel=preload as=script><link href=/css/chunk-vendors.cb63319e.css rel=stylesheet><link href=/css/app.fffbf4d6.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.d1dab075.js></script><script src=/js/app.b328f663.js></script></body></html>
|
||||
1
src/main/resources/static/js/adminIndex.0916d17e.js
Normal file
1
src/main/resources/static/js/adminIndex.0916d17e.js
Normal file
@@ -0,0 +1 @@
|
||||
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["adminIndex"],{"366e":function(t,e,i){"use strict";var a=i("479f"),s=i.n(a);s.a},"479f":function(t,e,i){},adf4:function(t,e,i){"use strict";i.r(e);var a=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/view"}},[i("i",{staticClass:"el-icon-view"}),i("span",{attrs:{slot:"title"},slot:"title"},[t._v("显示设置")])]),i("el-menu-item",{attrs:{index:"/admin/storage"}},[i("i",{staticClass:"el-icon-s-operation"}),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/cache"}},[i("i",{staticClass:"el-icon-collection"}),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 文档")])])],1)],1),i("el-col",{attrs:{span:16}},[i("keep-alive",{attrs:{exclude:"CacheManager,SiteSetting"}},[i("router-view")],1)],1)],1)},s=[],n={name:"Index",data:function(){return{active:"/admin/storage"}}},l=n,o=(i("366e"),i("2877")),r=Object(o["a"])(l,a,s,!1,null,"7f233ce7",null);e["default"]=r.exports}}]);
|
||||
@@ -1 +0,0 @@
|
||||
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["adminIndex"],{"197f":function(t,e,a){"use strict";var i=a("9e7d"),s=a.n(i);s.a},"9e7d":function(t,e,a){},adf4:function(t,e,a){"use strict";a.r(e);var i=function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("el-row",[a("el-col",{attrs:{span:3}},[a("el-menu",{staticClass:"el-menu-vertical-demo",attrs:{"default-active":"/admin"!==this.$route.path?this.$route.path:"/admin/site",router:!0}},[a("el-menu-item",{attrs:{index:"/admin/site"}},[a("i",{staticClass:"el-icon-setting"}),a("span",{attrs:{slot:"title"},slot:"title"},[t._v("站点设置")])]),a("el-menu-item",{attrs:{index:"/admin/storage"}},[a("i",{staticClass:"el-icon-s-operation"}),a("span",{attrs:{slot:"title"},slot:"title"},[t._v("存储策略")])]),a("el-menu-item",{attrs:{index:"/admin/password"}},[a("i",{staticClass:"el-icon-key"}),a("span",{attrs:{slot:"title"},slot:"title"},[t._v("修改密码")])]),a("el-menu-item",{attrs:{index:"/admin/cache"}},[a("i",{staticClass:"el-icon-collection"}),a("span",{attrs:{slot:"title"},slot:"title"},[t._v("缓存管理")])]),a("el-menu-item",{attrs:{index:"/admin/api"}},[a("i",{staticClass:"el-icon-document"}),a("span",{attrs:{slot:"title"},slot:"title"},[t._v("API 文档")])])],1)],1),a("el-col",{attrs:{span:16}},[a("keep-alive",{attrs:{exclude:"CacheManager,SiteSetting"}},[a("router-view")],1)],1)],1)},s=[],n={name:"Index",data:function(){return{active:"/admin/storage"}}},l=n,o=(a("197f"),a("2877")),r=Object(o["a"])(l,i,s,!1,null,"d26ac70e",null);e["default"]=r.exports}}]);
|
||||
File diff suppressed because one or more lines are too long
1
src/main/resources/static/js/app.b328f663.js
Normal file
1
src/main/resources/static/js/app.b328f663.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
Reference in New Issue
Block a user