🔖 版本更新

This commit is contained in:
zhaojun1998
2019-12-01 21:19:36 +08:00
parent 8f17423e1b
commit 9a7a6fb165
1375 changed files with 2429 additions and 367598 deletions

View File

@@ -4,7 +4,9 @@ import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.scheduling.annotation.EnableAsync;
@EnableAsync
@SpringBootApplication
@EnableCaching
@EnableAspectJAutoProxy(exposeProxy = true)

View File

@@ -1,114 +0,0 @@
package im.zhaojun.aliyun.service;
import cn.hutool.core.util.URLUtil;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.*;
import im.zhaojun.common.enums.FileTypeEnum;
import im.zhaojun.common.enums.StorageTypeEnum;
import im.zhaojun.common.model.FileItem;
import im.zhaojun.common.model.StorageConfig;
import im.zhaojun.common.service.FileService;
import im.zhaojun.common.service.StorageConfigService;
import im.zhaojun.common.util.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.net.URL;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
@Service
public class AliyunService implements FileService {
@Value("${zfile.cache.timeout}")
private Long timeout;
@Resource
private StorageConfigService storageConfigService;
private static final String BUCKET_NAME_KEY = "bucket-name";
private static final String ACCESS_KEY = "accessKey";
private static final String SECRET_KEY = "secretKey";
private static final String DOMAIN_KEY = "domain";
private static final String ENDPOINT_KEY = "endPoint";
private OSS ossClient;
private String bucketName;
private String domain;
private boolean isPrivate;
@Override
public void initMethod() {
Map<String, StorageConfig> stringStorageConfigMap =
storageConfigService.selectStorageConfigMapByKey(StorageTypeEnum.ALIYUN);
String accessKey = stringStorageConfigMap.get(ACCESS_KEY).getValue();
String secretKey = stringStorageConfigMap.get(SECRET_KEY).getValue();
String endPoint = stringStorageConfigMap.get(ENDPOINT_KEY).getValue();
bucketName = stringStorageConfigMap.get(BUCKET_NAME_KEY).getValue();
domain = stringStorageConfigMap.get(DOMAIN_KEY).getValue();
ossClient = new OSSClientBuilder().build(endPoint, accessKey, secretKey);
AccessControlList bucketAcl = ossClient.getBucketAcl(bucketName);
CannedAccessControlList cannedACL = bucketAcl.getCannedACL();
isPrivate = "Private".equals(cannedACL.name());
}
@Override
public List<FileItem> fileList(String path) {
path = StringUtils.removeFirstSeparator(path);
List<FileItem> fileItemList = new ArrayList<>();
ObjectListing objectListing =
ossClient.listObjects(new ListObjectsRequest(bucketName).withDelimiter("/").withPrefix(path));
for (OSSObjectSummary s : objectListing.getObjectSummaries()) {
FileItem fileItem = new FileItem();
fileItem.setName(s.getKey().substring(path.length()));
fileItem.setSize(s.getSize());
fileItem.setTime(s.getLastModified());
fileItem.setType(FileTypeEnum.FILE);
fileItem.setPath(path);
fileItemList.add(fileItem);
}
for (String commonPrefix : objectListing.getCommonPrefixes()) {
FileItem fileItem = new FileItem();
fileItem.setName(commonPrefix.substring(path.length(), commonPrefix.length() - 1));
fileItem.setType(FileTypeEnum.FOLDER);
fileItem.setPath(path);
fileItemList.add(fileItem);
}
return fileItemList;
}
@Override
public String getDownloadUrl(String path) throws Exception {
path = StringUtils.removeFirstSeparator(path);
if (isPrivate) {
Date expirationDate = new Date(new Date().getTime() + timeout * 1000);
URL url = ossClient.generatePresignedUrl(bucketName, path, expirationDate);
return URLUtil.complateUrl(domain, url.getFile());
} else {
return URLUtil.complateUrl(domain, path);
}
}
@Override
public StorageTypeEnum getStorageTypeEnum() {
return StorageTypeEnum.ALIYUN;
}
}

View File

@@ -0,0 +1,131 @@
package im.zhaojun.aliyun.service;
import cn.hutool.core.util.URLUtil;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.*;
import im.zhaojun.common.model.enums.FileTypeEnum;
import im.zhaojun.common.model.enums.StorageTypeEnum;
import im.zhaojun.common.model.dto.FileItemDTO;
import im.zhaojun.common.model.StorageConfig;
import im.zhaojun.common.service.FileService;
import im.zhaojun.common.service.StorageConfigService;
import im.zhaojun.common.util.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.net.URL;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
@Service
public class AliyunServiceImpl implements FileService {
private static final Logger log = LoggerFactory.getLogger(AliyunServiceImpl.class);
@Value("${zfile.cache.timeout}")
private Long timeout;
@Resource
private StorageConfigService storageConfigService;
private static final String BUCKET_NAME_KEY = "bucket-name";
private static final String ACCESS_KEY = "accessKey";
private static final String SECRET_KEY = "secretKey";
private static final String DOMAIN_KEY = "domain";
private static final String ENDPOINT_KEY = "endPoint";
private OSS ossClient;
private String bucketName;
private String domain;
private boolean isPrivate;
private boolean isInitialized;
@Override
public void init() {
try {
Map<String, StorageConfig> stringStorageConfigMap =
storageConfigService.selectStorageConfigMapByKey(StorageTypeEnum.ALIYUN);
String accessKey = stringStorageConfigMap.get(ACCESS_KEY).getValue();
String secretKey = stringStorageConfigMap.get(SECRET_KEY).getValue();
String endPoint = stringStorageConfigMap.get(ENDPOINT_KEY).getValue();
bucketName = stringStorageConfigMap.get(BUCKET_NAME_KEY).getValue();
domain = stringStorageConfigMap.get(DOMAIN_KEY).getValue();
ossClient = new OSSClientBuilder().build(endPoint, accessKey, secretKey);
AccessControlList bucketAcl = ossClient.getBucketAcl(bucketName);
CannedAccessControlList cannedAcl = bucketAcl.getCannedACL();
isPrivate = "Private".equals(cannedAcl.name());
isInitialized = true;
} catch (Exception e) {
log.debug(StorageTypeEnum.ALIYUN.getDescription() + "初始化异常, 已跳过");
}
}
@Override
public List<FileItemDTO> fileList(String path) {
path = StringUtils.removeFirstSeparator(path);
List<FileItemDTO> fileItemList = new ArrayList<>();
ObjectListing objectListing =
ossClient.listObjects(new ListObjectsRequest(bucketName).withDelimiter("/").withPrefix(path));
for (OSSObjectSummary s : objectListing.getObjectSummaries()) {
FileItemDTO fileItemDTO = new FileItemDTO();
fileItemDTO.setName(s.getKey().substring(path.length()));
fileItemDTO.setSize(s.getSize());
fileItemDTO.setTime(s.getLastModified());
fileItemDTO.setType(FileTypeEnum.FILE);
fileItemDTO.setPath(path);
fileItemDTO.setUrl(getDownloadUrl(StringUtils.concatUrl(path, fileItemDTO.getName())));
fileItemList.add(fileItemDTO);
}
for (String commonPrefix : objectListing.getCommonPrefixes()) {
FileItemDTO fileItemDTO = new FileItemDTO();
fileItemDTO.setName(commonPrefix.substring(path.length(), commonPrefix.length() - 1));
fileItemDTO.setType(FileTypeEnum.FOLDER);
fileItemDTO.setPath(path);
fileItemList.add(fileItemDTO);
}
return fileItemList;
}
@Override
public String getDownloadUrl(String path) {
path = StringUtils.removeFirstSeparator(path);
if (isPrivate) {
Date expirationDate = new Date(System.currentTimeMillis() + timeout * 1000);
URL url = ossClient.generatePresignedUrl(bucketName, path, expirationDate);
return URLUtil.complateUrl(domain, url.getFile());
} else {
return URLUtil.complateUrl(domain, path);
}
}
@Override
public StorageTypeEnum getStorageTypeEnum() {
return StorageTypeEnum.ALIYUN;
}
@Override
public boolean getIsInitialized() {
return isInitialized;
}
}

View File

@@ -0,0 +1,14 @@
package im.zhaojun.common.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 标记注解, 用于在调用前检查是否已存储策略
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface CheckStorageStrategyInit {
}

View File

@@ -0,0 +1,25 @@
package im.zhaojun.common.aspect;
import im.zhaojun.common.model.enums.StorageTypeEnum;
import im.zhaojun.common.exception.StorageStrategyUninitializedException;
import im.zhaojun.common.service.SystemConfigService;
import im.zhaojun.common.util.SpringContextHolder;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class StorageStrategyInitCheckAspect {
@Before("@annotation(im.zhaojun.common.annotation.CheckStorageStrategyInit)")
public void logStart() {
SystemConfigService systemConfigService = SpringContextHolder.getBean(SystemConfigService.class);
StorageTypeEnum currentStorageStrategy = systemConfigService.getCurrentStorageStrategy();
if (currentStorageStrategy == null) {
throw new StorageStrategyUninitializedException("存储策略未初始化");
}
}
}

View File

@@ -1,34 +1,36 @@
package im.zhaojun.common.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
import org.springframework.web.cors.CorsUtils;
import org.springframework.web.filter.GenericFilterBean;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebFilter(filterName = "CorsFilter")
@Configuration
public class CorsFilter implements Filter {
/**
* 开启跨域支持. 一般用于开发环境, 或前后端分离部署时开启.
*/
public class CorsFilter extends GenericFilterBean {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
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");
httpServletResponse.setHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true");
httpServletResponse.setHeader(HttpHeaders.ACCESS_CONTROL_MAX_AGE, "3600");
if (!CorsUtils.isPreFlightRequest(httpServletRequest)) {
chain.doFilter(httpServletRequest, httpServletResponse);
}
}
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) res;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, PATCH, DELETE, PUT");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
chain.doFilter(req, res);
}
@Override
public void destroy() {
}
}
}

View File

@@ -1,7 +1,6 @@
package im.zhaojun.common.config;
import im.zhaojun.common.enums.StorageTypeEnum;
import im.zhaojun.common.exception.UnknownStorageTypeException;
import im.zhaojun.common.model.enums.StorageTypeEnum;
import im.zhaojun.common.service.FileService;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
@@ -39,10 +38,6 @@ public class StorageTypeFactory implements ApplicationContextAware {
break;
}
}
if (result == null) {
throw new UnknownStorageTypeException(type.getDescription());
}
return result;
}

View File

@@ -0,0 +1,15 @@
package im.zhaojun.common.config;
import im.zhaojun.common.model.enums.StorageTypeEnumDeSerializerConvert;
import org.springframework.context.annotation.Configuration;
import org.springframework.format.FormatterRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addConverter(new StorageTypeEnumDeSerializerConvert());
}
}

View File

@@ -1,6 +1,5 @@
package im.zhaojun.common.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cache.caffeine.CaffeineCacheManager;
import org.springframework.cache.interceptor.KeyGenerator;
@@ -15,11 +14,11 @@ import org.springframework.data.redis.serializer.RedisSerializationContext;
import java.util.Collections;
/**
* 缓存配置类, 用于根据配置决定使用 redis 缓存还是 caffeine (内存).
*/
@Configuration
public class ZfileCacheConfiguration {
@Value("${zfile.cache.timeout}")
private Long timeout;
public class ZFileCacheConfiguration {
public static final String CACHE_NAME = "zfile";
@@ -34,6 +33,20 @@ public class ZfileCacheConfiguration {
return caffeineCacheManager;
}
@Bean
@ConditionalOnProperty(value = "spring.cache.type", havingValue = "redis")
public RedisCacheManager redisCacheManager(RedisConnectionFactory connectionFactory) {
RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(connectionFactory);
GenericJackson2JsonRedisSerializer jsonRedisSerializer
= new GenericJackson2JsonRedisSerializer();
RedisSerializationContext.SerializationPair<Object> pair
= RedisSerializationContext.SerializationPair.fromSerializer(jsonRedisSerializer);
RedisCacheConfiguration defaultCacheConfig=RedisCacheConfiguration.defaultCacheConfig().serializeValuesWith(pair);
return new RedisCacheManager(redisCacheWriter, defaultCacheConfig);
}
@Bean
public KeyGenerator keyGenerator() {
return (target, method, params) -> {
@@ -59,17 +72,4 @@ public class ZfileCacheConfiguration {
return strBuilder.toString();
};
}
@Bean
@ConditionalOnProperty(value = "spring.cache.type", havingValue = "redis")
public RedisCacheManager redisCacheManager(RedisConnectionFactory connectionFactory) {
RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(connectionFactory);
GenericJackson2JsonRedisSerializer jsonRedisSerializer
= new GenericJackson2JsonRedisSerializer();
RedisSerializationContext.SerializationPair<Object> pair
= RedisSerializationContext.SerializationPair.fromSerializer(jsonRedisSerializer);
RedisCacheConfiguration defaultCacheConfig=RedisCacheConfiguration.defaultCacheConfig().serializeValuesWith(pair);
return new RedisCacheManager(redisCacheWriter, defaultCacheConfig);
}
}

View File

@@ -8,7 +8,7 @@ import org.springframework.web.client.RestTemplate;
import java.nio.charset.StandardCharsets;
@Configuration
public class RestConfig {
public class ZFileConfiguration {
@Bean
public RestTemplate restTemplate(){
@@ -16,4 +16,5 @@ public class RestConfig {
restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
return restTemplate;
}
}
}

View File

@@ -1,11 +0,0 @@
package im.zhaojun.common.constant;
public class ZfileConstant {
public static final String HEADER_FILE_NAME = "header.md";
public static final String FOOTER_FILE_NAME = "footer.md";
public static final String PASSWORD_FILE_NAME = "password.txt";
}

View File

@@ -0,0 +1,115 @@
package im.zhaojun.common.controller;
import im.zhaojun.common.model.StorageConfig;
import im.zhaojun.common.model.enums.StorageTypeEnum;
import im.zhaojun.common.model.dto.ResultBean;
import im.zhaojun.common.model.SystemConfigDTO;
import im.zhaojun.common.service.FileAsyncCacheService;
import im.zhaojun.common.service.FileService;
import im.zhaojun.common.service.StorageConfigService;
import im.zhaojun.common.service.SystemConfigService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.List;
/**
* 后台管理
*/
@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("/update-pwd")
public ResultBean updatePwd(String username, String password) {
systemConfigService.updateUsernameAndPwd(username, password);
return ResultBean.success();
}
/**
* 更新系统配置
*/
@PostMapping("/config")
public ResultBean updateConfig(SystemConfigDTO systemConfigDTO) {
StorageTypeEnum currentStorageStrategy = systemConfigService.getCurrentStorageStrategy();
systemConfigDTO.setId(1);
systemConfigService.updateSystemConfig(systemConfigDTO);
if (!currentStorageStrategy.equals(systemConfigDTO.getStorageStrategy())) {
refreshStorageStrategy();
}
return ResultBean.success();
}
@GetMapping("/strategy-form")
public ResultBean getFormByStorageType(StorageTypeEnum storageType) {
List<StorageConfig> storageConfigList = storageConfigService.selectStorageConfigByType(storageType);
return ResultBean.success(storageConfigList);
}
/**
* 清理当前启用的存储引擎的缓存
*/
@GetMapping("/clear-cache")
public ResultBean clearCache() {
FileService fileService = systemConfigService.getCurrentFileService();
fileService.clearCache();
return ResultBean.success();
}
/**
* 更新存储策略
*/
public void refreshStorageStrategy() {
StorageTypeEnum storageStrategy = systemConfigService.getCurrentStorageStrategy();
refreshStorageStrategy(storageStrategy);
}
/**
* 更新存储策略
*/
public void refreshStorageStrategy(StorageTypeEnum storageStrategy) {
if (storageStrategy == null) {
log.info("尚未配置存储策略.");
} else {
FileService fileService = systemConfigService.getCurrentFileService();
fileService.init();
log.info("当前启用存储类型: {}", storageStrategy.getDescription());
// if 判断是否开启搜索.
fileAsyncCacheService.cacheGlobalFile();
}
}
}

View File

@@ -1,18 +1,18 @@
package im.zhaojun.common.controller;
import cn.hutool.core.util.URLUtil;
import im.zhaojun.common.config.StorageTypeFactory;
import im.zhaojun.common.constant.ZfileConstant;
import im.zhaojun.common.enums.StorageTypeEnum;
import im.zhaojun.common.annotation.CheckStorageStrategyInit;
import im.zhaojun.common.model.constant.ZFileConstant;
import im.zhaojun.common.model.enums.StorageTypeEnum;
import im.zhaojun.common.exception.SearchDisableException;
import im.zhaojun.common.model.FileItem;
import im.zhaojun.common.model.ResultBean;
import im.zhaojun.common.model.SiteConfig;
import im.zhaojun.common.model.ViewConfig;
import im.zhaojun.common.service.FileService;
import im.zhaojun.common.service.SystemService;
import im.zhaojun.common.service.ViewConfigService;
import im.zhaojun.common.model.*;
import im.zhaojun.common.model.dto.FileItemDTO;
import im.zhaojun.common.model.dto.ResultBean;
import im.zhaojun.common.model.dto.SiteConfigDTO;
import im.zhaojun.common.service.*;
import im.zhaojun.common.util.AudioHelper;
import im.zhaojun.common.util.FileComparator;
import im.zhaojun.common.util.HttpUtil;
import im.zhaojun.common.util.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -21,38 +21,43 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
/**
* 前台文件管理
*/
@RequestMapping("/api")
@RestController
public class FileController {
private static final Logger log = LoggerFactory.getLogger(FileController.class);
private FileService fileService;
@Resource
private SystemService systemService;
@Resource
private ViewConfigService viewConfigService;
private SystemConfigService systemConfigService;
public static final Integer PAGE_SIZE = 20;
@Resource
private StorageConfigService storageConfigService;
/**
* 滚动加载每页条数.
*/
private static final Integer PAGE_SIZE = 20;
@CheckStorageStrategyInit
@GetMapping("/list")
public ResultBean list(@RequestParam(defaultValue = "/") String path,
@RequestParam(defaultValue = "name") String sortBy,
@RequestParam(defaultValue = "asc") String order,
@RequestParam(required = false) String password,
@RequestParam(defaultValue = "1") Integer page) throws Exception {
List<FileItem> fileItems = fileService.fileList(StringUtils.removeDuplicateSeparator("/" + URLUtil.decode(path)));
for (FileItem fileItem : fileItems) {
if (ZfileConstant.PASSWORD_FILE_NAME.equals(fileItem.getName())) {
if (!fileService.getTextContent(fileItem.getUrl()).equals(password)) {
FileService fileService = systemConfigService.getCurrentFileService();
List<FileItemDTO> fileItemList = fileService.fileList(StringUtils.removeDuplicateSeparator("/" + URLUtil.decode(path) + "/"));
for (FileItemDTO fileItemDTO : fileItemList) {
if (ZFileConstant.PASSWORD_FILE_NAME.equals(fileItemDTO.getName())) {
if (!HttpUtil.getTextContent(fileItemDTO.getUrl()).equals(password)) {
if (password != null && !"".equals(password)) {
return ResultBean.error("密码错误.");
}
@@ -62,10 +67,10 @@ public class FileController {
}
// 排序, 先按照文件类型比较, 文件夹在前, 文件在后, 然后根据 sortBy 字段排序, 默认为升序;
fileItems.sort(new FileComparator(sortBy, order));
filterFileList(fileItems);
fileItemList.sort(new FileComparator(sortBy, order));
filterFileList(fileItemList);
Integer total = fileItems.size();
Integer total = fileItemList.size();
Integer totalPage = (total + PAGE_SIZE - 1) / PAGE_SIZE;
if (page > totalPage) {
@@ -75,7 +80,7 @@ public class FileController {
Integer start = (page - 1) * PAGE_SIZE;
Integer end = page * PAGE_SIZE;
end = end > total ? total : end;
List<FileItem> fileSubItem = fileItems.subList(start, end);
List<FileItemDTO> fileSubItem = fileItemList.subList(start, end);
return ResultBean.successData(fileSubItem);
}
@@ -84,83 +89,70 @@ public class FileController {
* @param url 文件路径
* @return 文件内容
*/
@CheckStorageStrategyInit
@GetMapping("/content")
public ResultBean getContent(String url) throws Exception {
return ResultBean.successData(fileService.getTextContent(url));
public ResultBean getContent(String url) {
return ResultBean.successData(HttpUtil.getTextContent(url));
}
/**
* 获取系统配置信息和当前页的标题, 文件头, 文件尾信息
* @param path 路径
*/
@CheckStorageStrategyInit
@GetMapping("/config")
public ResultBean getConfig(String path) throws Exception {
SiteConfig config = systemService.getConfig(URLUtil.decode(StringUtils.removeDuplicateSeparator("/" + path + "/")));
config.setViewConfig(viewConfigService.getViewConfig());
SiteConfigDTO config = systemService.getConfig(URLUtil.decode(StringUtils.removeDuplicateSeparator("/" + path + "/")));
config.setSystemConfigDTO(systemConfigService.getSystemConfig());
return ResultBean.successData(config);
}
/**
* 更新存储策略, 使用 @PostConstruct 注解, 以用于第一次启动时, 根据数据库的配置值, 读取默认的存储策略.
*/
@PostConstruct
@GetMapping("/updateStorageStrategy")
public ResultBean updateConfig() {
ViewConfig viewConfig = viewConfigService.getViewConfig();
StorageTypeEnum storageStrategy = viewConfig.getStorageStrategy();
fileService = StorageTypeFactory.getStorageTypeService(storageStrategy);
log.info("当前启用存储类型: {}", storageStrategy.getDescription());
// new Thread(() -> {
// log.info("缓存 {} 所有文件开始", storageStrategy.getDescription());
// long startTime = System.currentTimeMillis();
// try {
// fileService.selectAllFileList();
// } catch (Exception e) {
// log.error("缓存所有文件失败", e);
// e.printStackTrace();
// }
// long endTime = System.currentTimeMillis();
// log.info("缓存 {} 所有文件结束, 用时: {} 秒", storageStrategy.getDescription(), ( (endTime - startTime) / 1000 ));
// }).start();
return ResultBean.success();
}
@CheckStorageStrategyInit
@GetMapping("/clearCache")
public ResultBean clearCache() throws Exception {
fileService.clearCache();
public ResultBean clearCache() {
FileService fileService = systemConfigService.getCurrentFileService();
if (fileService != null) {
fileService.clearCache();
}
return ResultBean.success();
}
@GetMapping("/getImageInfo")
public ResultBean getImageInfo(String url) throws Exception {
return ResultBean.success(fileService.getImageInfo(url));
}
@CheckStorageStrategyInit
@GetMapping("/audioInfo")
public ResultBean getAudioInfo(String url) throws Exception {
return ResultBean.success(fileService.getAudioInfo(url));
return ResultBean.success(AudioHelper.getAudioInfo(url));
}
@CheckStorageStrategyInit
@GetMapping("/search")
public ResultBean search(@RequestParam(value = "name", defaultValue = "/") String name) throws Exception {
ViewConfig viewConfig = viewConfigService.getViewConfig();
if (!viewConfig.getSearchEnable()) {
FileService fileService = systemConfigService.getCurrentFileService();
SystemConfigDTO systemConfigDTO = systemConfigService.getSystemConfig();
if (!systemConfigDTO.getSearchEnable()) {
throw new SearchDisableException("搜索功能未开启");
}
return ResultBean.success(fileService.search(URLUtil.decode(name)));
}
@GetMapping("/form")
public ResultBean getFormByStorageType(String storageType) {
StorageTypeEnum storageTypeEnum = StorageTypeEnum.getEnum(storageType);
List<StorageConfig> storageConfigList = storageConfigService.selectStorageConfigByType(storageTypeEnum);
storageConfigList.forEach(storageConfig -> storageConfig.setValue(null));
return ResultBean.success(storageConfigList);
}
/**
* 过滤文件列表, 不显示密码, 头部和尾部文件.
*/
private void filterFileList(List<FileItem> fileItemList) {
private void filterFileList(List<FileItemDTO> fileItemList) {
if (fileItemList == null) {
return;
}
fileItemList.removeIf(fileItem -> ZfileConstant.PASSWORD_FILE_NAME.equals(fileItem.getName())
|| ZfileConstant.FOOTER_FILE_NAME.equals(fileItem.getName())
|| ZfileConstant.HEADER_FILE_NAME.equals(fileItem.getName()));
fileItemList.removeIf(fileItem -> ZFileConstant.PASSWORD_FILE_NAME.equals(fileItem.getName())
|| ZFileConstant.FOOTER_FILE_NAME.equals(fileItem.getName())
|| ZFileConstant.HEADER_FILE_NAME.equals(fileItem.getName()));
}
}

View File

@@ -1,40 +0,0 @@
package im.zhaojun.common.controller;
import im.zhaojun.common.service.ViewConfigService;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.servlet.ModelAndView;
import javax.annotation.Resource;
@Controller
public class IndexController {
@Resource
private ViewConfigService viewConfigService;
@GetMapping("/")
public String index() {
return "redirect:/file/";
}
@GetMapping("/file/**")
public ModelAndView index(ModelAndView modelAndView) {
modelAndView.setViewName("index");
modelAndView.addObject("viewConfig", viewConfigService.getViewConfig());
return modelAndView;
}
@GetMapping("/admin")
public ModelAndView admin(ModelAndView modelAndView) {
modelAndView.setViewName("admin");
modelAndView.addObject("viewConfig", viewConfigService.getViewConfig());
return modelAndView;
}
@GetMapping("/install")
public ModelAndView install(ModelAndView modelAndView) {
modelAndView.setViewName("install");
return modelAndView;
}
}

View File

@@ -0,0 +1,103 @@
package im.zhaojun.common.controller;
import im.zhaojun.common.config.WebMvcConfig;
import im.zhaojun.common.model.StorageConfig;
import im.zhaojun.common.model.SystemConfigDTO;
import im.zhaojun.common.model.dto.InstallModelDTO;
import im.zhaojun.common.model.dto.ResultBean;
import im.zhaojun.common.model.enums.StorageTypeEnum;
import im.zhaojun.common.service.FileService;
import im.zhaojun.common.service.StorageConfigService;
import im.zhaojun.common.service.SystemConfigService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Controller;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.HandlerMapping;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.util.List;
import java.util.Map;
import java.util.Objects;
/**
* 系统安装初始化
*/
@Controller
public class InstallController {
@Resource
private SystemConfigService systemConfigService;
@Resource
private StorageConfigService storageConfigService;
@Resource
private AdminController adminController;
@GetMapping("/is-installed")
@ResponseBody
public ResultBean isInstall() {
if (systemConfigService.getCurrentStorageStrategy() == null) {
return ResultBean.success();
}
return ResultBean.error("请勿重复初始化");
}
@PostMapping("/install")
@ResponseBody
public ResultBean install(InstallModelDTO installModelDTO) {
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(new BCryptPasswordEncoder().encode(installModelDTO.getPassword()));
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();
}
@PostMapping("/storage-strategy")
@ResponseBody
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);
StorageTypeEnum currentStorageStrategy = systemConfigService.getCurrentStorageStrategy();
if (Objects.equals(storageStrategy, currentStorageStrategy)) {
FileService fileService = systemConfigService.getCurrentFileService();
fileService.clearCache();
fileService.init();
}
return ResultBean.success();
}
}

View File

@@ -1,38 +0,0 @@
package im.zhaojun.common.enums;
import com.fasterxml.jackson.annotation.JsonValue;
import java.util.HashMap;
import java.util.Map;
public enum ViewModeEnum {
DETAILS("details"), ICONS("icons"), GRID("grid");
private static Map<String, ViewModeEnum> enumMap = new HashMap<>();
static {
for (ViewModeEnum type : ViewModeEnum.values()) {
enumMap.put(type.getValue(), type);
}
}
String value;
ViewModeEnum(String value) {
this.value = value;
}
@JsonValue
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public static ViewModeEnum getEnum(String value) {
return enumMap.get(value);
}
}

View File

@@ -1,19 +0,0 @@
package im.zhaojun.common.enums;
import javax.persistence.AttributeConverter;
import javax.persistence.Converter;
@Converter(autoApply = true)
public class ViewModeEnumConvert implements AttributeConverter<ViewModeEnum, String> {
@Override
public String convertToDatabaseColumn(ViewModeEnum attribute) {
return attribute.value;
}
@Override
public ViewModeEnum convertToEntityAttribute(String dbData) {
return ViewModeEnum.getEnum(dbData);
}
}

View File

@@ -1,9 +1,11 @@
package im.zhaojun.common.exception;
import im.zhaojun.common.model.ResultBean;
import im.zhaojun.common.model.dto.ResultBean;
import org.apache.catalina.connector.ClientAbortException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.web.HttpMediaTypeNotAcceptableException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
@@ -27,4 +29,35 @@ public class GlobleExceptionHandler {
return ResultBean.error(e.getMessage());
}
@ExceptionHandler
@ResponseStatus
public ResultBean searchDisableExceptionHandler(StorageStrategyUninitializedException e) {
if (log.isDebugEnabled()) {
log.debug(e.getMessage(), e);
}
return ResultBean.error(e.getMessage());
}
/**
* 捕获 ClientAbortException 异常, 不做任何处理, 防止出现大量堆栈日志输出, 此异常不影响功能.
*/
@ExceptionHandler({HttpMediaTypeNotAcceptableException.class, ClientAbortException.class})
@ResponseBody
@ResponseStatus
public void clientAbortException(Exception ex) {
// if (log.isDebugEnabled()) {
// log.debug("出现了断开异常:", ex);
// }
}
@ExceptionHandler
@ResponseStatus(code= HttpStatus.INTERNAL_SERVER_ERROR)
public ResultBean searchDisableExceptionHandler(Exception e) {
if (log.isDebugEnabled()) {
log.debug(e.getMessage(), e);
}
return ResultBean.error("系统异常, 请联系管理员");
}
}

View File

@@ -0,0 +1,28 @@
package im.zhaojun.common.exception;
/**
* 对象存储初始化异常
*/
public class InitializeException extends RuntimeException {
private static final long serialVersionUID = -1920550904063819880L;
public InitializeException() {
}
public InitializeException(String message) {
super(message);
}
public InitializeException(String message, Throwable cause) {
super(message, cause);
}
public InitializeException(Throwable cause) {
super(cause);
}
public InitializeException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}

View File

@@ -0,0 +1,28 @@
package im.zhaojun.common.exception;
/**
* 存储策略未初始化异常
*/
public class StorageStrategyUninitializedException extends RuntimeException {
private static final long serialVersionUID = 5736940575583615661L;
public StorageStrategyUninitializedException() {
}
public StorageStrategyUninitializedException(String message) {
super(message);
}
public StorageStrategyUninitializedException(String message, Throwable cause) {
super(message, cause);
}
public StorageStrategyUninitializedException(Throwable cause) {
super(cause);
}
public StorageStrategyUninitializedException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}

View File

@@ -1,14 +0,0 @@
package im.zhaojun.common.model;
public class FolderItem {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

View File

@@ -1,29 +0,0 @@
package im.zhaojun.common.model;
public class ImageInfo {
private Integer width;
private Integer height;
public ImageInfo() {}
public ImageInfo(Integer width, Integer height) {
this.width = width;
this.height = height;
}
public Integer getWidth() {
return width;
}
public void setWidth(Integer width) {
this.width = width;
}
public Integer getHeight() {
return height;
}
public void setHeight(Integer height) {
this.height = height;
}
}

View File

@@ -1,38 +0,0 @@
package im.zhaojun.common.model;
import java.io.Serializable;
public class SiteConfig implements Serializable {
private static final long serialVersionUID = 8811196207046121740L;
private String header;
private String footer;
private ViewConfig viewConfig;
public String getHeader() {
return header;
}
public void setHeader(String header) {
this.header = header;
}
public String getFooter() {
return footer;
}
public void setFooter(String footer) {
this.footer = footer;
}
public ViewConfig getViewConfig() {
return viewConfig;
}
public void setViewConfig(ViewConfig viewConfig) {
this.viewConfig = viewConfig;
}
}

View File

@@ -1,14 +1,11 @@
package im.zhaojun.common.model;
import im.zhaojun.common.enums.StorageTypeEnum;
import im.zhaojun.common.model.enums.StorageTypeEnum;
import lombok.Data;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.*;
@Entity
@Entity(name = "STORAGE_CONFIG")
@Data
public class StorageConfig {
@@ -18,6 +15,7 @@ public class StorageConfig {
private StorageTypeEnum type;
@Column(name = "`key`")
private String key;
private String title;

View File

@@ -0,0 +1,54 @@
package im.zhaojun.common.model;
import im.zhaojun.common.model.enums.StorageTypeEnum;
import lombok.Data;
import javax.persistence.*;
@Entity(name = "SYSTEM_CONFIG")
@Data
public class SystemConfig {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@Column(name = "`key`")
private String key;
private String value;
private String remark;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public String getRemark() {
return remark;
}
public void setRemark(String remark) {
this.remark = remark;
}
}

View File

@@ -1,39 +1,31 @@
package im.zhaojun.common.model;
import com.fasterxml.jackson.annotation.JsonIgnore;
import im.zhaojun.common.enums.StorageTypeEnum;
import im.zhaojun.common.enums.ViewModeEnum;
import lombok.Data;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import im.zhaojun.common.model.enums.StorageTypeEnum;
import im.zhaojun.common.model.enums.StorageTypeEnumSerializerConvert;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity(name = "SYSTEM_CONFIG")
@Data
public class ViewConfig {
public class SystemConfigDTO {
@JsonIgnore
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String siteName;
private ViewModeEnum mode;
private Boolean sidebarEnable;
private Boolean infoEnable;
private Boolean searchEnable;
private Boolean searchIgnoreCase;
@JsonIgnore
@JsonSerialize(using = StorageTypeEnumSerializerConvert.class)
private StorageTypeEnum storageStrategy;
private String username;
@JsonIgnore
private String password;
public Integer getId() {
return id;
}
@@ -50,22 +42,6 @@ public class ViewConfig {
this.siteName = siteName;
}
public ViewModeEnum getMode() {
return mode;
}
public void setMode(ViewModeEnum mode) {
this.mode = mode;
}
public Boolean getSidebarEnable() {
return sidebarEnable;
}
public void setSidebarEnable(Boolean sidebarEnable) {
this.sidebarEnable = sidebarEnable;
}
public Boolean getInfoEnable() {
return infoEnable;
}
@@ -97,4 +73,20 @@ public class ViewConfig {
public void setStorageStrategy(StorageTypeEnum storageStrategy) {
this.storageStrategy = storageStrategy;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}

View File

@@ -0,0 +1,19 @@
package im.zhaojun.common.model.constant;
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";
public static final String STORAGE_STRATEGY = "storageStrategy";
public static final String USERNAME = "username";
public static final String PASSWORD = "password";
}

View File

@@ -0,0 +1,24 @@
package im.zhaojun.common.model.constant;
public class ZFileConstant {
public final static String USER_HOME = System.getProperty("user.home");
public static final String AUDIO_TMP_PATH = "/.zfile/tmp/audio/";
/**
* 页面头部文件
*/
public static final String HEADER_FILE_NAME = "header.md";
/**
* 页面尾部文件
*/
public static final String FOOTER_FILE_NAME = "footer.md";
/**
* 密码文件
*/
public static final String PASSWORD_FILE_NAME = "password.txt";
}

View File

@@ -1,6 +1,6 @@
package im.zhaojun.common.model;
package im.zhaojun.common.model.dto;
public class AudioInfo {
public class AudioInfoDTO {
private String title;
private String artist;
private String cover;
@@ -37,4 +37,14 @@ public class AudioInfo {
public void setSrc(String src) {
this.src = src;
}
@Override
public String toString() {
return "AudioInfoDTO{" +
"title='" + title + '\'' +
", artist='" + artist + '\'' +
", cover='" + cover + '\'' +
", src='" + src + '\'' +
'}';
}
}

View File

@@ -1,11 +1,11 @@
package im.zhaojun.common.model;
package im.zhaojun.common.model.dto;
import im.zhaojun.common.enums.FileTypeEnum;
import im.zhaojun.common.model.enums.FileTypeEnum;
import java.io.Serializable;
import java.util.Date;
public class FileItem implements Serializable {
public class FileItemDTO implements Serializable {
private String name;
private Date time;
@@ -61,4 +61,16 @@ public class FileItem implements Serializable {
public void setUrl(String url) {
this.url = url;
}
@Override
public String toString() {
return "FileItemDTO{" +
"name='" + name + '\'' +
", time=" + time +
", size=" + size +
", type=" + type +
", path='" + path + '\'' +
", url='" + url + '\'' +
'}';
}
}

View File

@@ -0,0 +1,64 @@
package im.zhaojun.common.model.dto;
import im.zhaojun.common.model.enums.StorageTypeEnum;
import java.util.Map;
public class InstallModelDTO {
private String siteName;
private StorageTypeEnum storageStrategy;
private String username;
private String password;
private Map<String, String> storageStrategyConfig;
public String getSiteName() {
return siteName;
}
public void setSiteName(String siteName) {
this.siteName = siteName;
}
public StorageTypeEnum getStorageStrategy() {
return storageStrategy;
}
public void setStorageStrategy(StorageTypeEnum storageStrategy) {
this.storageStrategy = storageStrategy;
}
public Map<String, String> getStorageStrategyConfig() {
return storageStrategyConfig;
}
public void setStorageStrategyConfig(Map<String, String> storageStrategyConfig) {
this.storageStrategyConfig = storageStrategyConfig;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "InstallModelDTO{" +
"siteName='" + siteName + '\'' +
", storageStrategy=" + storageStrategy +
", username='" + username + '\'' +
", password='" + password + '\'' +
", storageStrategyConfig=" + storageStrategyConfig +
'}';
}
}

View File

@@ -1,4 +1,4 @@
package im.zhaojun.common.model;
package im.zhaojun.common.model.dto;
import java.io.Serializable;

View File

@@ -0,0 +1,49 @@
package im.zhaojun.common.model.dto;
import im.zhaojun.common.model.SystemConfigDTO;
import java.io.Serializable;
public class SiteConfigDTO implements Serializable {
private static final long serialVersionUID = 8811196207046121740L;
private String header;
private String footer;
private SystemConfigDTO systemConfigDTO;
public String getHeader() {
return header;
}
public void setHeader(String header) {
this.header = header;
}
public String getFooter() {
return footer;
}
public void setFooter(String footer) {
this.footer = footer;
}
public SystemConfigDTO getSystemConfigDTO() {
return systemConfigDTO;
}
public void setSystemConfigDTO(SystemConfigDTO systemConfigDTO) {
this.systemConfigDTO = systemConfigDTO;
}
@Override
public String toString() {
return "SiteConfigDTO{" +
"header='" + header + '\'' +
", footer='" + footer + '\'' +
", systemConfig=" + systemConfigDTO +
'}';
}
}

View File

@@ -1,7 +1,16 @@
package im.zhaojun.common.enums;
package im.zhaojun.common.model.enums;
public enum FileTypeEnum {
FILE("File"), FOLDER("Folder");
/**
* 文件
*/
FILE("File"),
/**
* 文件夹
*/
FOLDER("Folder");
private String value;

View File

@@ -1,17 +1,20 @@
package im.zhaojun.common.enums;
package im.zhaojun.common.model.enums;
import java.util.HashMap;
import java.util.Map;
public enum StorageTypeEnum {
/**
* 当前系统支持的所有存储策略
*/
UPYUN("upyun", "又拍云 USS"),
QINIU("qiniu", "七牛云 KODO"),
HUAWEI("huawei", "华为云 OBS"),
ALIYUN("aliyun", "阿里云 OSS"),
FTP("ftp", "FTP"),
LOCAL("local", "本地存储"),
TENCENT("tencent", "腾讯云 COS");;
TENCENT("tencent", "腾讯云 COS");
private static Map<String, StorageTypeEnum> enumMap = new HashMap<>();

View File

@@ -1,4 +1,4 @@
package im.zhaojun.common.enums;
package im.zhaojun.common.model.enums;
import javax.persistence.AttributeConverter;
import javax.persistence.Converter;

View File

@@ -0,0 +1,11 @@
package im.zhaojun.common.model.enums;
import org.springframework.core.convert.converter.Converter;
public class StorageTypeEnumDeSerializerConvert implements Converter<String, StorageTypeEnum> {
@Override
public StorageTypeEnum convert(String s) {
return StorageTypeEnum.getEnum(s);
}
}

View File

@@ -0,0 +1,15 @@
package im.zhaojun.common.model.enums;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import java.io.IOException;
public class StorageTypeEnumSerializerConvert extends JsonSerializer<StorageTypeEnum> {
@Override
public void serialize(StorageTypeEnum storageTypeEnum, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
jsonGenerator.writeString(storageTypeEnum.getKey());
}
}

View File

@@ -1,7 +1,7 @@
package im.zhaojun.common.repository;
import im.zhaojun.common.enums.StorageTypeEnum;
import im.zhaojun.common.model.StorageConfig;
import im.zhaojun.common.model.enums.StorageTypeEnum;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@@ -10,6 +10,6 @@ import java.util.List;
@Repository
public interface StorageConfigRepository extends JpaRepository<StorageConfig, Integer> {
public List<StorageConfig> findByType(StorageTypeEnum type);
List<StorageConfig> findByTypeOrderById(StorageTypeEnum type);
}

View File

@@ -0,0 +1,11 @@
package im.zhaojun.common.repository;
import im.zhaojun.common.model.SystemConfig;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface SystemConfigRepository extends JpaRepository<SystemConfig, Integer> {
SystemConfig findByKey(String key);
}

View File

@@ -1,12 +0,0 @@
package im.zhaojun.common.repository;
import im.zhaojun.common.model.ViewConfig;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface ViewConfigRepository extends JpaRepository<ViewConfig, Integer> {
public ViewConfig findFirstBy();
}

View File

@@ -0,0 +1,23 @@
package im.zhaojun.common.security;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
@Configuration
public class MyCorsFilter {
@Bean
public CorsFilter corsFilter() {
final UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource();
final CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.setAllowCredentials(true);
corsConfiguration.addAllowedOrigin("*");
corsConfiguration.addAllowedHeader("*");
corsConfiguration.addAllowedMethod("*");
urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration);
return new CorsFilter(urlBasedCorsConfigurationSource);
}
}

View File

@@ -0,0 +1,124 @@
package im.zhaojun.common.security;
import com.fasterxml.jackson.databind.ObjectMapper;
import im.zhaojun.common.model.dto.ResultBean;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
/**
* 自定义Security配置类
*/
@EnableWebSecurity
public class MySecurityConfig extends WebSecurityConfigurerAdapter {
@Resource
private ObjectMapper objectMapper;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
// .authenticationProvider(authenticationProvider())
.exceptionHandling()
//未登录时进行json格式的提示很喜欢这种写法不用单独写一个又一个的类
.authenticationEntryPoint((request, response, authException) -> {
response.setContentType("application/json;charset=utf-8");
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
PrintWriter out = response.getWriter();
out.write(objectMapper.writeValueAsString(ResultBean.error("未登录")));
out.flush();
out.close();
})
.and()
.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/admin/**").authenticated()
.and()
.formLogin() //使用自带的登录
//登录失败返回json
.failureHandler((request, response, ex) -> {
response.setContentType("application/json;charset=utf-8");
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
PrintWriter out = response.getWriter();
String msg;
if (ex instanceof UsernameNotFoundException || ex instanceof BadCredentialsException) {
msg = "用户名或密码错误";
} else {
msg = "登录失败";
}
out.write(objectMapper.writeValueAsString(ResultBean.error(msg)));
out.flush();
out.close();
})
//登录成功返回json
.successHandler((request, response, authentication) -> {
response.setContentType("application/json;charset=utf-8");
PrintWriter out = response.getWriter();
out.write(objectMapper.writeValueAsString(ResultBean.success(authentication)));
out.flush();
out.close();
})
.and()
.exceptionHandling()
//没有权限返回json
.accessDeniedHandler((request, response, ex) -> {
response.setContentType("application/json;charset=utf-8");
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
PrintWriter out = response.getWriter();
out.write(objectMapper.writeValueAsString(ResultBean.error("权限不足")));
out.flush();
out.close();
})
.and()
.logout()
//退出成功返回json
.logoutSuccessHandler((request, response, authentication) -> {
response.setContentType("application/json;charset=utf-8");
PrintWriter out = response.getWriter();
out.write(objectMapper.writeValueAsString(ResultBean.error("注销成功")));
out.flush();
out.close();
})
.and()
.logout().permitAll();
http.cors();
http.csrf().disable();
}
@Override
public void configure(AuthenticationManagerBuilder web) throws Exception {
web.userDetailsService(myUserDetailsServiceImpl()).passwordEncoder(passwordEncoder());
}
@Bean
public MyUserDetailsServiceImpl myUserDetailsServiceImpl() {
return new MyUserDetailsServiceImpl();
}
@Override
public void configure(WebSecurity web) {
//对于在header里面增加token等类似情况放行所有OPTIONS请求。
web.ignoring().antMatchers(HttpMethod.OPTIONS, "/**");
}
@Bean
public static PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}

View File

@@ -0,0 +1,26 @@
package im.zhaojun.common.security;
import im.zhaojun.common.model.SystemConfigDTO;
import im.zhaojun.common.service.SystemConfigService;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import javax.annotation.Resource;
import java.util.Collections;
public class MyUserDetailsServiceImpl implements UserDetailsService {
@Resource
private SystemConfigService systemConfigService;
/**
* 授权的时候是对角色授权,认证的时候应该基于资源,而不是角色,因为资源是不变的,而用户的角色是会变的
*/
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
SystemConfigDTO systemConfig = systemConfigService.getSystemConfig();
return new User(systemConfig.getUsername(), systemConfig.getPassword(), Collections.emptyList());
}
}

View File

@@ -0,0 +1,43 @@
package im.zhaojun.common.service;
import im.zhaojun.common.config.StorageTypeFactory;
import im.zhaojun.common.model.enums.StorageTypeEnum;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@Service
public class FileAsyncCacheService {
private static final Logger log = LoggerFactory.getLogger(FileAsyncCacheService.class);
@Resource
private SystemConfigService systemConfigService;
@Async
public void cacheGlobalFile() {
StorageTypeEnum storageStrategy = systemConfigService.getCurrentStorageStrategy();
if (storageStrategy == null) {
log.info("尚未配置存储策略. 跳过启动缓存.");
return;
}
FileService fileService = StorageTypeFactory.getStorageTypeService(storageStrategy);
log.info("缓存 {} 所有文件开始", storageStrategy.getDescription());
long startTime = System.currentTimeMillis();
try {
if (fileService.getIsInitialized()) {
fileService.selectAllFileList();
}
} catch (Exception e) {
log.error("缓存所有文件失败", e);
e.printStackTrace();
}
long endTime = System.currentTimeMillis();
log.info("缓存 {} 所有文件结束, 用时: {} 秒", storageStrategy.getDescription(), ( (endTime - startTime) / 1000 ));
}
}

View File

@@ -1,122 +1,65 @@
package im.zhaojun.common.service;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.URLUtil;
import cn.hutool.http.HttpUtil;
import im.zhaojun.common.config.ZfileCacheConfiguration;
import im.zhaojun.common.enums.FileTypeEnum;
import im.zhaojun.common.enums.StorageTypeEnum;
import im.zhaojun.common.model.AudioInfo;
import im.zhaojun.common.model.FileItem;
import im.zhaojun.common.model.ImageInfo;
import im.zhaojun.common.util.AudioHelper;
import im.zhaojun.common.util.SpringContextHolder;
import im.zhaojun.common.config.ZFileCacheConfiguration;
import im.zhaojun.common.model.dto.FileItemDTO;
import im.zhaojun.common.model.enums.FileTypeEnum;
import im.zhaojun.common.model.enums.StorageTypeEnum;
import im.zhaojun.common.util.StringUtils;
import org.springframework.aop.framework.AopContext;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.web.client.RestTemplate;
import javax.annotation.PostConstruct;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.List;
@CacheConfig(cacheNames = ZfileCacheConfiguration.CACHE_NAME, keyGenerator = "keyGenerator")
@CacheConfig(cacheNames = ZFileCacheConfiguration.CACHE_NAME, keyGenerator = "keyGenerator")
public interface FileService {
@Cacheable
List<FileItem> fileList(String path) throws Exception;
List<FileItemDTO> fileList(String path) throws Exception;
@Cacheable
String getDownloadUrl(String path) throws Exception;
/**
* 获取文件内容.
*/
default String getTextContent(String url) throws Exception {
RestTemplate restTemplate = SpringContextHolder.getBean(RestTemplate.class);
String result = restTemplate.getForObject(url, String.class);
return result == null ? "" : result;
}
@PostConstruct
default void initMethod() throws Exception {}
default void init() {}
/**
* 清除缓存.
*/
@CacheEvict(allEntries = true)
default void clearCache() throws Exception {
}
default void clearCache() {}
/**
* 获取图片信息
* @param url 图片 URL
* @return 图片的信息, 宽、高
*/
@Cacheable
default ImageInfo getImageInfo(String url) throws Exception {
url = URLUtil.decode(url);
URL urlObject = new URL(url);
String originPath = urlObject.getPath();
url = url.replace(originPath, URLUtil.encode(originPath));
InputStream inputStream = new URL(url).openStream();
BufferedImage sourceImg = ImageIO.read(inputStream);
return new ImageInfo(sourceImg.getWidth(), sourceImg.getHeight());
}
default List<FileItemDTO> search(String name) throws Exception {
List<FileItemDTO> result = new ArrayList<>();
default AudioInfo getAudioInfo(String url) throws Exception {
String query = new URL(URLUtil.decode(url)).getQuery();
if (query != null) {
url = url.replace(query, URLUtil.encode(query));
}
File file = new File(System.getProperty("user.home") + "/zfile/tmp/audio/" + UUID.fastUUID());
FileUtil.mkParentDirs(file);
HttpUtil.downloadFile(url, file);
AudioInfo audioInfo = AudioHelper.parseAudioInfo(file);
audioInfo.setSrc(url);
file.deleteOnExit();
return audioInfo;
}
default List<FileItem> search(String name) throws Exception {
List<FileItem> result = new ArrayList<>();
List<FileItem> fileItemList = selectAllFileList();
for (FileItem fileItem : fileItemList) {
if (fileItem.getName().contains(name)) {
result.add(fileItem);
List<FileItemDTO> fileItemList = selectAllFileList();
for (FileItemDTO fileItemDTO : fileItemList) {
if (fileItemDTO.getName().contains(name)) {
result.add(fileItemDTO);
}
}
return result;
}
default List<FileItem> selectAllFileList() throws Exception {
List<FileItem> result = new ArrayList<>();
default List<FileItemDTO> selectAllFileList() throws Exception {
List<FileItemDTO> result = new ArrayList<>();
String path = "/";
FileService currentFileService = (FileService) AopContext.currentProxy();
List<FileItem> fileItemList = currentFileService.fileList(path);
ArrayDeque<FileItem> queue = new ArrayDeque<>(fileItemList);
List<FileItemDTO> fileItemList = currentFileService.fileList(path);
ArrayDeque<FileItemDTO> queue = new ArrayDeque<>(fileItemList);
while (!queue.isEmpty()) {
FileItem fileItem = queue.pop();
result.add(fileItem);
if (fileItem.getType() == FileTypeEnum.FOLDER) {
String filePath = StringUtils.removeDuplicateSeparator("/" + fileItem.getPath() + "/" + fileItem.getName() + "/");
FileItemDTO fileItemDTO = queue.pop();
result.add(fileItemDTO);
if (fileItemDTO.getType() == FileTypeEnum.FOLDER) {
String filePath = StringUtils.removeDuplicateSeparator("/" + fileItemDTO.getPath() + "/" + fileItemDTO.getName() + "/");
queue.addAll(currentFileService.fileList(filePath));
}
}
@@ -125,4 +68,6 @@ public interface FileService {
}
StorageTypeEnum getStorageTypeEnum();
boolean getIsInitialized();
}

View File

@@ -1,6 +1,6 @@
package im.zhaojun.common.service;
import im.zhaojun.common.enums.StorageTypeEnum;
import im.zhaojun.common.model.enums.StorageTypeEnum;
import im.zhaojun.common.model.StorageConfig;
import im.zhaojun.common.repository.StorageConfigRepository;
import org.springframework.stereotype.Service;
@@ -16,15 +16,20 @@ public class StorageConfigService {
@Resource
private StorageConfigRepository storageConfigRepository;
private List<StorageConfig> selectStorageConfigByType(StorageTypeEnum storageTypeEnum) {
return storageConfigRepository.findByType(storageTypeEnum);
public List<StorageConfig> selectStorageConfigByType(StorageTypeEnum storageTypeEnum) {
return storageConfigRepository.findByTypeOrderById(storageTypeEnum);
}
public Map<String, StorageConfig> selectStorageConfigMapByKey(StorageTypeEnum storageTypeEnum) {
Map<String, StorageConfig> map = new HashMap<>();
Map<String, StorageConfig> map = new HashMap<>(24);
for (StorageConfig storageConfig : selectStorageConfigByType(storageTypeEnum)) {
map.put(storageConfig.getKey(), storageConfig);
}
return map;
}
public void updateStorageConfig(List<StorageConfig> storageConfigList) {
storageConfigRepository.saveAll(storageConfigList);
}
}

View File

@@ -0,0 +1,118 @@
package im.zhaojun.common.service;
import im.zhaojun.common.config.StorageTypeFactory;
import im.zhaojun.common.model.SystemConfig;
import im.zhaojun.common.model.SystemConfigDTO;
import im.zhaojun.common.model.constant.SystemConfigConstant;
import im.zhaojun.common.model.enums.StorageTypeEnum;
import im.zhaojun.common.repository.SystemConfigRepository;
import im.zhaojun.common.util.StringUtils;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
@Service
public class SystemConfigService {
@Resource
private SystemConfigRepository systemConfigRepository;
public SystemConfigDTO getSystemConfig() {
SystemConfigDTO systemConfigDTO = new SystemConfigDTO();
List<SystemConfig> systemConfigList = systemConfigRepository.findAll();
for (SystemConfig systemConfig : systemConfigList) {
switch (systemConfig.getKey()) {
case SystemConfigConstant.SITE_NAME:
systemConfigDTO.setSiteName(systemConfig.getValue());
break;
case SystemConfigConstant.INFO_ENABLE:
systemConfigDTO.setInfoEnable("true".equals(systemConfig.getValue()));
break;
case SystemConfigConstant.SEARCH_ENABLE:
systemConfigDTO.setSearchEnable("true".equals(systemConfig.getValue()));
break;
case SystemConfigConstant.SEARCH_IGNORE_CASE:
systemConfigDTO.setSearchIgnoreCase("true".equals(systemConfig.getValue()));
break;
case SystemConfigConstant.STORAGE_STRATEGY:
String value = systemConfig.getValue();
systemConfigDTO.setStorageStrategy(StorageTypeEnum.getEnum(value));
break;
case SystemConfigConstant.USERNAME:
systemConfigDTO.setUsername(systemConfig.getValue());
break;
case SystemConfigConstant.PASSWORD:
systemConfigDTO.setPassword(systemConfig.getValue());
break;
default:break;
}
}
return systemConfigDTO;
}
public void updateSystemConfig(SystemConfigDTO systemConfigDTO) {
List<SystemConfig> systemConfigList = new ArrayList<>();
SystemConfig systemConfig = systemConfigRepository.findByKey(SystemConfigConstant.SITE_NAME);
systemConfig.setValue(systemConfigDTO.getSiteName());
systemConfigList.add(systemConfig);
SystemConfig infoEnableSystemConfig = systemConfigRepository.findByKey(SystemConfigConstant.INFO_ENABLE);
infoEnableSystemConfig.setValue(systemConfigDTO.getInfoEnable() ? "true" : "false");
systemConfigList.add(infoEnableSystemConfig);
SystemConfig searchEnableSystemConfig = systemConfigRepository.findByKey(SystemConfigConstant.SEARCH_ENABLE);
searchEnableSystemConfig.setValue(systemConfigDTO.getSearchEnable() ? "true" : "false");
systemConfigList.add(searchEnableSystemConfig);
SystemConfig searchIgnoreCaseSystemConfig = systemConfigRepository.findByKey(SystemConfigConstant.SEARCH_IGNORE_CASE);
searchIgnoreCaseSystemConfig.setValue(systemConfigDTO.getSearchIgnoreCase() ? "true" : "false");
systemConfigList.add(searchIgnoreCaseSystemConfig);
SystemConfig storageStrategySystemConfig = systemConfigRepository.findByKey(SystemConfigConstant.STORAGE_STRATEGY);
storageStrategySystemConfig.setValue(systemConfigDTO.getStorageStrategy().getKey());
systemConfigList.add(storageStrategySystemConfig);
if (!StringUtils.isNullOrEmpty(systemConfigDTO.getUsername())) {
SystemConfig usernameSystemConfig = systemConfigRepository.findByKey(SystemConfigConstant.USERNAME);
usernameSystemConfig.setValue(systemConfigDTO.getUsername());
systemConfigList.add(usernameSystemConfig);
}
if (!StringUtils.isNullOrEmpty(systemConfigDTO.getPassword())) {
SystemConfig passwordSystemConfig = systemConfigRepository.findByKey(SystemConfigConstant.PASSWORD);
passwordSystemConfig.setValue(systemConfigDTO.getPassword());
systemConfigList.add(passwordSystemConfig);
}
systemConfigRepository.saveAll(systemConfigList);
}
public void updateUsernameAndPwd(String username, String password) {
SystemConfig usernameConfig = systemConfigRepository.findByKey(SystemConfigConstant.USERNAME);
usernameConfig.setValue(username);
systemConfigRepository.save(usernameConfig);
password = new BCryptPasswordEncoder().encode(password);
SystemConfig systemConfig = systemConfigRepository.findByKey(SystemConfigConstant.PASSWORD);
systemConfig.setValue(password);
systemConfigRepository.save(systemConfig);
}
public FileService getCurrentFileService() {
StorageTypeEnum storageStrategy = getCurrentStorageStrategy();
return StorageTypeFactory.getStorageTypeService(storageStrategy);
}
public StorageTypeEnum getCurrentStorageStrategy() {
SystemConfigDTO systemConfigDTO = getSystemConfig();
return systemConfigDTO.getStorageStrategy();
}
}

View File

@@ -1,9 +1,9 @@
package im.zhaojun.common.service;
import im.zhaojun.common.constant.ZfileConstant;
import im.zhaojun.common.model.FileItem;
import im.zhaojun.common.model.SiteConfig;
import im.zhaojun.common.util.StringUtils;
import im.zhaojun.common.model.constant.ZFileConstant;
import im.zhaojun.common.model.dto.FileItemDTO;
import im.zhaojun.common.model.dto.SiteConfigDTO;
import im.zhaojun.common.util.HttpUtil;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@@ -13,27 +13,26 @@ import java.util.List;
public class SystemService {
@Resource
private ViewConfigService viewConfigService;
private SystemConfigService systemConfigService;
/**
* 构建指定路径下标题, 页头, 页尾
* @param path 路径
*/
public SiteConfig getConfig(String path) throws Exception {
public SiteConfigDTO getConfig(String path) throws Exception {
SiteConfig siteConfig = new SiteConfig();
FileService fileService = viewConfigService.getCurrentFileService();
SiteConfigDTO siteConfigDTO = new SiteConfigDTO();
FileService fileService = systemConfigService.getCurrentFileService();
List<FileItem> fileItemList = fileService.fileList(path);
path = StringUtils.removeLastSeparator(path);
for (FileItem fileItem : fileItemList) {
if (ZfileConstant.FOOTER_FILE_NAME.equalsIgnoreCase(fileItem.getName())) {
siteConfig.setFooter(fileService.getTextContent(fileItem.getUrl()));
} else if (ZfileConstant.HEADER_FILE_NAME.equalsIgnoreCase(fileItem.getName())) {
siteConfig.setHeader(fileService.getTextContent(fileItem.getUrl()));
List<FileItemDTO> fileItemList = fileService.fileList(path);
for (FileItemDTO fileItemDTO : fileItemList) {
if (ZFileConstant.FOOTER_FILE_NAME.equalsIgnoreCase(fileItemDTO.getName())) {
siteConfigDTO.setFooter(HttpUtil.getTextContent(fileItemDTO.getUrl()));
} else if (ZFileConstant.HEADER_FILE_NAME.equalsIgnoreCase(fileItemDTO.getName())) {
siteConfigDTO.setHeader(HttpUtil.getTextContent(fileItemDTO.getUrl()));
}
}
return siteConfig;
return siteConfigDTO;
}
}

View File

@@ -1,27 +0,0 @@
package im.zhaojun.common.service;
import im.zhaojun.common.config.StorageTypeFactory;
import im.zhaojun.common.enums.StorageTypeEnum;
import im.zhaojun.common.model.ViewConfig;
import im.zhaojun.common.repository.ViewConfigRepository;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@Service
public class ViewConfigService {
@Resource
private ViewConfigRepository viewConfigRepository;
public ViewConfig getViewConfig() {
return viewConfigRepository.findFirstBy();
}
public FileService getCurrentFileService() {
ViewConfig viewConfig = getViewConfig();
StorageTypeEnum storageStrategy = viewConfig.getStorageStrategy();
return StorageTypeFactory.getStorageTypeService(storageStrategy);
}
}

View File

@@ -1,23 +1,49 @@
package im.zhaojun.common.util;
import cn.hutool.core.codec.Base64;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.URLUtil;
import cn.hutool.http.HttpUtil;
import com.mpatric.mp3agic.*;
import im.zhaojun.common.model.AudioInfo;
import im.zhaojun.common.model.constant.ZFileConstant;
import im.zhaojun.common.model.dto.AudioInfoDTO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.IOException;
import java.net.URL;
/**
* 音频解析工具类
*/
public class AudioHelper {
private static final Logger log = LoggerFactory.getLogger(AudioHelper.class);
public static AudioInfo parseAudioInfo(File file) throws InvalidDataException, IOException, UnsupportedTagException {
AudioInfo audioInfo = new AudioInfo();
audioInfo.setTitle("未知歌曲");
audioInfo.setArtist("未知");
audioInfo.setCover("/shikwasa/audio.png");
public static AudioInfoDTO getAudioInfo(String url) throws Exception {
String query = new URL(URLUtil.decode(url)).getQuery();
if (query != null) {
url = url.replace(query, URLUtil.encode(query));
}
File file = new File(ZFileConstant.USER_HOME + ZFileConstant.AUDIO_TMP_PATH + UUID.fastUUID());
FileUtil.mkParentDirs(file);
HttpUtil.downloadFile(url, file);
AudioInfoDTO audioInfoDTO = parseAudioInfo(file);
audioInfoDTO.setSrc(url);
file.deleteOnExit();
return audioInfoDTO;
}
private static AudioInfoDTO parseAudioInfo(File file) throws IOException, UnsupportedTagException {
AudioInfoDTO audioInfoDTO = new AudioInfoDTO();
audioInfoDTO.setTitle("未知歌曲");
audioInfoDTO.setArtist("未知");
audioInfoDTO.setCover("/shikwasa/audio.png");
Mp3File mp3File = null;
try {
@@ -29,7 +55,7 @@ public class AudioHelper {
}
if (mp3File == null) {
return audioInfo;
return audioInfoDTO;
}
ID3v1 audioTag = null;
@@ -38,16 +64,16 @@ public class AudioHelper {
ID3v2 id3v2Tag = mp3File.getId3v2Tag();
byte[] albumImage = id3v2Tag.getAlbumImage();
if (albumImage != null) {
audioInfo.setCover("data:" + id3v2Tag.getAlbumImageMimeType() + ";base64," + Base64.encode(albumImage));
audioInfoDTO.setCover("data:" + id3v2Tag.getAlbumImageMimeType() + ";base64," + Base64.encode(albumImage));
}
audioTag = id3v2Tag;
}
if (audioTag != null) {
audioInfo.setTitle(audioTag.getTitle());
audioInfo.setArtist(audioTag.getArtist());
audioInfoDTO.setTitle(audioTag.getTitle());
audioInfoDTO.setArtist(audioTag.getArtist());
}
return audioInfo;
return audioInfoDTO;
}
}

View File

@@ -1,7 +1,7 @@
package im.zhaojun.common.util;
import im.zhaojun.common.enums.FileTypeEnum;
import im.zhaojun.common.model.FileItem;
import im.zhaojun.common.model.enums.FileTypeEnum;
import im.zhaojun.common.model.dto.FileItemDTO;
import java.util.Comparator;
@@ -13,7 +13,7 @@ import java.util.Comparator;
* - 默认排序为升序
* - 按名称排序不区分大小写
*/
public class FileComparator implements Comparator<FileItem> {
public class FileComparator implements Comparator<FileItemDTO> {
private String sortBy;
private String order;
@@ -24,7 +24,7 @@ public class FileComparator implements Comparator<FileItem> {
}
@Override
public int compare(FileItem o1, FileItem o2) {
public int compare(FileItemDTO o1, FileItemDTO o2) {
FileTypeEnum o1Type = o1.getType();
FileTypeEnum o2Type = o2.getType();

View File

@@ -0,0 +1,13 @@
package im.zhaojun.common.util;
import org.springframework.web.client.RestTemplate;
public class HttpUtil {
public static String getTextContent(String url) {
RestTemplate restTemplate = SpringContextHolder.getBean(RestTemplate.class);
String result = restTemplate.getForObject(url, String.class);
return result == null ? "" : result;
}
}

View File

@@ -54,13 +54,13 @@ public class SpringContextHolder implements ApplicationContextAware, DisposableB
* 实现 DisposableBean 接口, 在 Context 关闭时清理静态变量.
*/
@Override
public void destroy() throws Exception {
public void destroy() {
SpringContextHolder.clearHolder();
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
SpringContextHolder.applicationContext = applicationContext;
}
}

View File

@@ -1,10 +1,6 @@
package im.zhaojun.common.util;
import im.zhaojun.common.config.StorageTypeFactory;
import im.zhaojun.common.enums.StorageTypeEnum;
import im.zhaojun.common.model.ViewConfig;
import im.zhaojun.common.service.FileService;
import im.zhaojun.common.service.ViewConfigService;
import im.zhaojun.common.service.FileAsyncCacheService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationListener;
@@ -20,26 +16,17 @@ import javax.annotation.Resource;
public class StartupListener implements ApplicationListener<ContextRefreshedEvent> {
private static final Logger log = LoggerFactory.getLogger(StartupListener.class);
@Resource
private ViewConfigService viewConfigService;
private FileAsyncCacheService fileAsyncCacheService;
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
ViewConfig viewConfig = viewConfigService.getViewConfig();
StorageTypeEnum storageStrategy = viewConfig.getStorageStrategy();
FileService fileService = StorageTypeFactory.getStorageTypeService(storageStrategy);
new Thread(() -> {
log.info("缓存 {} 所有文件开始", storageStrategy.getDescription());
long startTime = System.currentTimeMillis();
try {
fileService.selectAllFileList();
} catch (Exception e) {
log.error("缓存所有文件失败", e);
e.printStackTrace();
}
long endTime = System.currentTimeMillis();
log.info("缓存 {} 所有文件结束, 用时: {} 秒", storageStrategy.getDescription(), ( (endTime - startTime) / 1000 ));
}).start();
try {
fileAsyncCacheService.cacheGlobalFile();
} catch (Exception e) {
throw new RuntimeException("缓存异常.", e);
}
}
}

View File

@@ -24,7 +24,7 @@ public class StringUtils {
return path;
}
public static String concatURL(String path, String name) {
public static String concatUrl(String path, String name) {
return removeDuplicateSeparator("/" + path + "/" + name);
}
@@ -71,4 +71,9 @@ public class StringUtils {
return sb.toString();
}
public static boolean isNullOrEmpty(String s) {
return s == null || "".equals(s);
}
}

View File

@@ -1,79 +0,0 @@
package im.zhaojun.ftp.service;
import cn.hutool.core.util.URLUtil;
import cn.hutool.extra.ftp.Ftp;
import im.zhaojun.common.enums.FileTypeEnum;
import im.zhaojun.common.enums.StorageTypeEnum;
import im.zhaojun.common.model.FileItem;
import im.zhaojun.common.model.StorageConfig;
import im.zhaojun.common.service.FileService;
import im.zhaojun.common.service.StorageConfigService;
import org.apache.commons.net.ftp.FTPFile;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@Service
public class FtpService implements FileService {
@Resource
private StorageConfigService storageConfigService;
private static final String HOST_KEY = "host";
private static final String PORT_KEY = "port";
private static final String USERNAME_KEY = "username";
private static final String PASSWORD_KEY = "password";
private static final String DOMAIN_KEY = "domain";
private Ftp ftp;
private String domain;
@Override
public void initMethod() {
Map<String, StorageConfig> stringStorageConfigMap =
storageConfigService.selectStorageConfigMapByKey(StorageTypeEnum.FTP);
String host = stringStorageConfigMap.get(HOST_KEY).getValue();
String port = stringStorageConfigMap.get(PORT_KEY).getValue();
String username = stringStorageConfigMap.get(USERNAME_KEY).getValue();
String password = stringStorageConfigMap.get(PASSWORD_KEY).getValue();
domain = stringStorageConfigMap.get(DOMAIN_KEY).getValue();
ftp = new Ftp(host, Integer.parseInt(port), username, password);
}
@Override
public List<FileItem> fileList(String path) {
FTPFile[] ftpFiles = ftp.lsFiles(path);
List<FileItem> fileItemList = new ArrayList<>();
for (FTPFile ftpFile : ftpFiles) {
FileItem fileItem = new FileItem();
fileItem.setName(ftpFile.getName());
fileItem.setSize(ftpFile.getSize());
fileItem.setTime(ftpFile.getTimestamp().getTime());
fileItem.setType(ftpFile.isDirectory() ? FileTypeEnum.FOLDER : FileTypeEnum.FILE);
fileItem.setPath(path);
fileItemList.add(fileItem);
}
return fileItemList;
}
@Override
public String getDownloadUrl(String path) {
return URLUtil.complateUrl(domain, path);
}
@Override
public StorageTypeEnum getStorageTypeEnum() {
return StorageTypeEnum.FTP;
}
}

View File

@@ -0,0 +1,100 @@
package im.zhaojun.ftp.service;
import cn.hutool.core.util.URLUtil;
import cn.hutool.extra.ftp.Ftp;
import im.zhaojun.common.model.enums.FileTypeEnum;
import im.zhaojun.common.model.enums.StorageTypeEnum;
import im.zhaojun.common.model.dto.FileItemDTO;
import im.zhaojun.common.model.StorageConfig;
import im.zhaojun.common.service.FileService;
import im.zhaojun.common.service.StorageConfigService;
import im.zhaojun.common.util.StringUtils;
import org.apache.commons.net.ftp.FTPFile;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@Service
public class FtpServiceImpl implements FileService {
private static final Logger log = LoggerFactory.getLogger(FtpServiceImpl.class);
@Resource
private StorageConfigService storageConfigService;
private static final String HOST_KEY = "host";
private static final String PORT_KEY = "port";
private static final String USERNAME_KEY = "username";
private static final String PASSWORD_KEY = "password";
private static final String DOMAIN_KEY = "domain";
private Ftp ftp;
private String domain;
private boolean isInitialized;
@Override
public void init() {
try {
Map<String, StorageConfig> stringStorageConfigMap =
storageConfigService.selectStorageConfigMapByKey(StorageTypeEnum.FTP);
String host = stringStorageConfigMap.get(HOST_KEY).getValue();
String port = stringStorageConfigMap.get(PORT_KEY).getValue();
String username = stringStorageConfigMap.get(USERNAME_KEY).getValue();
String password = stringStorageConfigMap.get(PASSWORD_KEY).getValue();
domain = stringStorageConfigMap.get(DOMAIN_KEY).getValue();
ftp = new Ftp(host, Integer.parseInt(port), username, password);
isInitialized = true;
} catch (Exception e) {
log.debug(StorageTypeEnum.FTP.getDescription() + "初始化异常, 已跳过");
}
}
@Override
public List<FileItemDTO> fileList(String path) {
FTPFile[] ftpFiles = ftp.lsFiles(path);
List<FileItemDTO> fileItemList = new ArrayList<>();
for (FTPFile ftpFile : ftpFiles) {
FileItemDTO fileItemDTO = new FileItemDTO();
fileItemDTO.setName(ftpFile.getName());
fileItemDTO.setSize(ftpFile.getSize());
fileItemDTO.setTime(ftpFile.getTimestamp().getTime());
fileItemDTO.setType(ftpFile.isDirectory() ? FileTypeEnum.FOLDER : FileTypeEnum.FILE);
fileItemDTO.setPath(path);
if (ftpFile.isFile()) {
fileItemDTO.setUrl(getDownloadUrl(StringUtils.concatUrl(path, fileItemDTO.getName())));
}
fileItemList.add(fileItemDTO);
}
return fileItemList;
}
@Override
public String getDownloadUrl(String path) {
return URLUtil.complateUrl(domain, path);
}
@Override
public StorageTypeEnum getStorageTypeEnum() {
return StorageTypeEnum.FTP;
}
@Override
public boolean getIsInitialized() {
return isInitialized;
}
}

View File

@@ -3,13 +3,15 @@ package im.zhaojun.huawei.service;
import cn.hutool.core.util.URLUtil;
import com.obs.services.ObsClient;
import com.obs.services.model.*;
import im.zhaojun.common.enums.FileTypeEnum;
import im.zhaojun.common.enums.StorageTypeEnum;
import im.zhaojun.common.model.FileItem;
import im.zhaojun.common.model.enums.FileTypeEnum;
import im.zhaojun.common.model.enums.StorageTypeEnum;
import im.zhaojun.common.model.dto.FileItemDTO;
import im.zhaojun.common.model.StorageConfig;
import im.zhaojun.common.service.FileService;
import im.zhaojun.common.service.StorageConfigService;
import im.zhaojun.common.util.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
@@ -20,7 +22,9 @@ import java.util.List;
import java.util.Map;
@Service
public class HuaweiService implements FileService {
public class HuaweiServiceImpl implements FileService {
private static final Logger log = LoggerFactory.getLogger(HuaweiServiceImpl.class);
private String bucketName;
@@ -44,24 +48,31 @@ public class HuaweiService implements FileService {
private ObsClient obsClient;
@Override
public void initMethod() {
Map<String, StorageConfig> stringStorageConfigMap =
storageConfigService.selectStorageConfigMapByKey(StorageTypeEnum.HUAWEI);
String accessKey = stringStorageConfigMap.get(ACCESS_KEY).getValue();
String secretKey = stringStorageConfigMap.get(SECRET_KEY).getValue();
String endPoint = stringStorageConfigMap.get(ENDPOINT_KEY).getValue();
private boolean isInitialized;
bucketName = stringStorageConfigMap.get(BUCKET_NAME_KEY).getValue();
domain = stringStorageConfigMap.get(DOMAIN_KEY).getValue();
obsClient = new ObsClient(accessKey, secretKey, endPoint);
@Override
public void init() {
try {
Map<String, StorageConfig> stringStorageConfigMap =
storageConfigService.selectStorageConfigMapByKey(StorageTypeEnum.HUAWEI);
String accessKey = stringStorageConfigMap.get(ACCESS_KEY).getValue();
String secretKey = stringStorageConfigMap.get(SECRET_KEY).getValue();
String endPoint = stringStorageConfigMap.get(ENDPOINT_KEY).getValue();
bucketName = stringStorageConfigMap.get(BUCKET_NAME_KEY).getValue();
domain = stringStorageConfigMap.get(DOMAIN_KEY).getValue();
obsClient = new ObsClient(accessKey, secretKey, endPoint);
isInitialized = true;
} catch (Exception e) {
log.debug(StorageTypeEnum.HUAWEI.getDescription() + "初始化异常, 已跳过");
}
}
@Override
public List<FileItem> fileList(String path) {
public List<FileItemDTO> fileList(String path) throws Exception {
path = StringUtils.removeFirstSeparator(path);
List<FileItem> fileItemList = new ArrayList<>();
List<FileItemDTO> fileItemList = new ArrayList<>();
ListObjectsRequest listObjectsRequest = new ListObjectsRequest();
listObjectsRequest.setBucketName(bucketName);
@@ -74,21 +85,22 @@ public class HuaweiService implements FileService {
String fileName = object.getObjectKey();
ObjectMetadata metadata = object.getMetadata();
FileItem fileItem = new FileItem();
fileItem.setName(fileName.substring(path.length()));
fileItem.setSize(metadata.getContentLength());
fileItem.setTime(metadata.getLastModified());
fileItem.setType(FileTypeEnum.FILE);
fileItem.setPath(path);
fileItemList.add(fileItem);
FileItemDTO fileItemDTO = new FileItemDTO();
fileItemDTO.setName(fileName.substring(path.length()));
fileItemDTO.setSize(metadata.getContentLength());
fileItemDTO.setTime(metadata.getLastModified());
fileItemDTO.setType(FileTypeEnum.FILE);
fileItemDTO.setPath(path);
fileItemDTO.setUrl(getDownloadUrl(StringUtils.concatUrl(path, fileItemDTO.getName())));
fileItemList.add(fileItemDTO);
}
for (String commonPrefix : objectListing.getCommonPrefixes()) {
FileItem fileItem = new FileItem();
fileItem.setName(commonPrefix.substring(0, commonPrefix.length() - 1));
fileItem.setType(FileTypeEnum.FOLDER);
fileItem.setPath(path);
fileItemList.add(fileItem);
FileItemDTO fileItemDTO = new FileItemDTO();
fileItemDTO.setName(commonPrefix.substring(0, commonPrefix.length() - 1));
fileItemDTO.setType(FileTypeEnum.FOLDER);
fileItemDTO.setPath(path);
fileItemList.add(fileItemDTO);
}
return fileItemList;
@@ -109,4 +121,12 @@ public class HuaweiService implements FileService {
public StorageTypeEnum getStorageTypeEnum() {
return StorageTypeEnum.HUAWEI;
}
@Override
public boolean getIsInitialized() {
return isInitialized;
}
}

View File

@@ -2,16 +2,19 @@ package im.zhaojun.local.controller;
import cn.hutool.core.util.URLUtil;
import im.zhaojun.common.util.StringUtils;
import im.zhaojun.local.service.LocalService;
import im.zhaojun.local.service.LocalServiceImpl;
import org.springframework.core.io.FileSystemResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
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.ResponseBody;
import org.springframework.web.servlet.HandlerMapping;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
@@ -21,12 +24,18 @@ import java.util.Date;
public class LocalController {
@Resource
private LocalService localService;
private LocalServiceImpl localServiceImpl;
@GetMapping("/local-download")
@GetMapping("/file/**")
@ResponseBody
public ResponseEntity<FileSystemResource> downAttachment(String fileName) throws IOException {
return export(new File(StringUtils.concatPath(localService.getFilePath(), URLUtil.decode(fileName))));
public ResponseEntity<FileSystemResource> downAttachment(final HttpServletRequest request) throws IOException {
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))));
}
private ResponseEntity<FileSystemResource> export(File file) throws IOException {
@@ -36,7 +45,6 @@ public class LocalController {
MediaType mediaType = MediaType.APPLICATION_OCTET_STREAM;
HttpHeaders headers = new HttpHeaders();
// 如果
if (fileMimeType == null || "".equals(fileMimeType)) {
headers.add("Cache-Control", "no-cache, no-store, must-revalidate");
headers.add("Content-Disposition", "attachment; filename=" + file.getName());
@@ -55,5 +63,4 @@ public class LocalController {
.body(new FileSystemResource(file));
}
}

View File

@@ -1,111 +0,0 @@
package im.zhaojun.local.service;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.URLUtil;
import im.zhaojun.common.enums.FileTypeEnum;
import im.zhaojun.common.enums.StorageTypeEnum;
import im.zhaojun.common.model.FileItem;
import im.zhaojun.common.model.ImageInfo;
import im.zhaojun.common.model.StorageConfig;
import im.zhaojun.common.service.FileService;
import im.zhaojun.common.service.StorageConfigService;
import im.zhaojun.common.util.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.InputStream;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.URL;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
@Service
public class LocalService implements FileService {
private static final String FILE_PATH_KEY = "filePath";
@Value("${server.port}")
private String port;
@Value("${server.servlet.context-path}")
private String contextPath;
@Resource
private StorageConfigService storageConfigService;
private String filePath;
@Override
public void initMethod() {
Map<String, StorageConfig> stringStorageConfigMap =
storageConfigService.selectStorageConfigMapByKey(StorageTypeEnum.LOCAL);
filePath = stringStorageConfigMap.get(FILE_PATH_KEY).getValue();
}
@Override
public List<FileItem> fileList(String path) throws Exception {
List<FileItem> fileItemList = new ArrayList<>();
String fullPath = StringUtils.concatPath(filePath, path);
File file = new File(fullPath);
File[] files = file.listFiles();
if (files == null) {
return fileItemList;
}
for (File f : files) {
FileItem fileItem = new FileItem();
fileItem.setType(f.isDirectory() ? FileTypeEnum.FOLDER : FileTypeEnum.FILE);
fileItem.setTime(new Date(f.lastModified()));
fileItem.setSize(f.length());
fileItem.setName(f.getName());
fileItem.setPath(path);
if (!f.isDirectory()) {
fileItem.setUrl(getDownloadUrl(StringUtils.concatURL(path, f.getName())));
}
fileItemList.add(fileItem);
}
return fileItemList;
}
@Override
public String getDownloadUrl(String path) throws Exception {
InetAddress localHost = Inet4Address.getLocalHost();
String host = localHost.getHostAddress();
return StringUtils.concatPath( "http://" + host + ":" + port + contextPath, "local-download?fileName=" + path);
}
@Override
public ImageInfo getImageInfo(String url) throws Exception {
String query = new URL(URLUtil.decode(url)).getQuery();
url = url.replace(query, URLUtil.encode(query));
InputStream inputStream = new URL(url).openStream();
BufferedImage sourceImg = ImageIO.read(inputStream);
return new ImageInfo(sourceImg.getWidth(), sourceImg.getHeight());
}
public String getFilePath() {
return filePath;
}
public void setFilePath(String filePath) {
this.filePath = filePath;
}
@Override
public StorageTypeEnum getStorageTypeEnum() {
return StorageTypeEnum.LOCAL;
}
}

View File

@@ -0,0 +1,111 @@
package im.zhaojun.local.service;
import cn.hutool.core.util.URLUtil;
import im.zhaojun.common.model.enums.FileTypeEnum;
import im.zhaojun.common.model.enums.StorageTypeEnum;
import im.zhaojun.common.model.dto.FileItemDTO;
import im.zhaojun.common.model.StorageConfig;
import im.zhaojun.common.service.FileService;
import im.zhaojun.common.service.StorageConfigService;
import im.zhaojun.common.util.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.io.File;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
@Service
public class LocalServiceImpl implements FileService {
private static final Logger log = LoggerFactory.getLogger(LocalServiceImpl.class);
private static final String FILE_PATH_KEY = "filePath";
@Value("${server.port}")
private String port;
@Value("${server.servlet.context-path}")
private String contextPath;
@Resource
private StorageConfigService storageConfigService;
private String filePath;
private boolean isInitialized;
@Override
public void init() {
try {
Map<String, StorageConfig> stringStorageConfigMap =
storageConfigService.selectStorageConfigMapByKey(StorageTypeEnum.LOCAL);
filePath = stringStorageConfigMap.get(FILE_PATH_KEY).getValue();
isInitialized = true;
} catch (Exception e) {
log.debug(StorageTypeEnum.LOCAL.getDescription() + "初始化异常, 已跳过");
}
}
@Override
public List<FileItemDTO> fileList(String path) throws Exception {
List<FileItemDTO> fileItemList = new ArrayList<>();
String fullPath = StringUtils.concatPath(filePath, path);
File file = new File(fullPath);
File[] files = file.listFiles();
if (files == null) {
return fileItemList;
}
for (File f : files) {
FileItemDTO fileItemDTO = new FileItemDTO();
fileItemDTO.setType(f.isDirectory() ? FileTypeEnum.FOLDER : FileTypeEnum.FILE);
fileItemDTO.setTime(new Date(f.lastModified()));
fileItemDTO.setSize(f.length());
fileItemDTO.setName(f.getName());
fileItemDTO.setPath(path);
if (f.isFile()) {
fileItemDTO.setUrl(getDownloadUrl(StringUtils.concatUrl(path, f.getName())));
}
fileItemList.add(fileItemDTO);
}
return fileItemList;
}
@Override
public String getDownloadUrl(String path) throws Exception {
InetAddress localHost = Inet4Address.getLocalHost();
String host = localHost.getHostAddress();
return StringUtils.concatPath( "http://" + host + ":" + port + contextPath, "file" + path);
}
public String getFilePath() {
return filePath;
}
public void setFilePath(String filePath) {
this.filePath = filePath;
}
@Override
public StorageTypeEnum getStorageTypeEnum() {
return StorageTypeEnum.LOCAL;
}
@Override
public boolean getIsInitialized() {
return isInitialized;
}
}

View File

@@ -0,0 +1,35 @@
// package im.zhaojun.onedrive.config;
//
// import org.nuxeo.onedrive.client.*;
// import org.springframework.context.annotation.Configuration;
//
// @Configuration
// public class OneDriveConfig {
//
//
// public void a () {
// OneDriveAPI api = new OneDriveBasicAPI("YOUR_ACCESS_TOKEN");
//
// OneDriveFolder folder = new OneDriveFolder(api, "FOLDER_ID");
// OneDriveFile file = new OneDriveFile(api, "FILE_ID");
// }
//
// public static void main(String[] args) throws OneDriveAPIException {
// OneDriveBasicAPI api = new OneDriveBasicAPI("EwAgA61DBAAUcSSzoTJJsy+XrnQXgAKO5cj4yc8AAQ0ZknDUY8YnwB9aJv7vA9YjiRAVMnKc+rG11fSXLZRAA8Q/CgJaz+OkRN60vaLDfp6KxbmVlob6kxeD/peOUI2eHtk0055Q2+n057tlyVAvGIFl9dvqkItoAthjmybcSkKBZS5h1meWxQ5IOvzSVrdgCKL0NOtTxfh33ZUDsYjvSid6NOX4Bs+pRjvZhQkvqEfGt8KlOL+JoIowmv2I+u09iDmS60BMwSoeK2K3CCLIXxLaiiPYUMsrNk65j4PWEBwBEfyHb6j3lrM/YvwFLq7Y8KJVjrXjFENC7ruja6Ko/cfTMX90yLkUEckpsZ30E6RJHWEHt7jXtNwndDZVknYDZgAACL5pnk17FJfb8AGGxJL1Y0CnAzgkTM2gw+WkFRRDDNzujuW1LQofwZ119HdeANhPrBZ14x32VaPGL1l0RvtR9LCeAN+EogcV5xhVpmCExitaXQB6OkZ6BnXaxLj5TNvFRNeZq0ZfJ3T08clLA1vXHkZhNKgiFDI8xUbahy4r6QpzgoF+0+dz+MA1NzQCQCsRGieS63OD1BKrzRsNxzls5Z9rKzBT6CpWpiaiOg4mmW0yeino/L9zz9Gf5kAJr813bpNr+rH/E8MPd0pZf+6hv37FaVCM7RN1V7CkkCDnRAxwxEK8pDgZhRjZOw7gKutPOiOoTO9ptjh2Jcrds714HitX2HI3RsRY+yyAOcb8XI27m4daSEGCJCuu/TJwXTE4ul54MWsi8MrcDlZN9DOjckiJIqVI8IbvhM+OUAP4FUIfZJJrIVa8WFwxcsMmjlLTxp/I7+JfdvZjJSk3j1yYvbWFviyoSkpQgw2hIDhZxCg083Z6qS467g5H9Uz3fQc+Ss0K0Mud6RcZTU9RqCcp+h92tUc8+gDxQ2NwJsG5vcmSRwf5KHKvsWjt6yK4OHxCpkLYi31eJZtv2EjQGXX1gYyhc/2wQ+cHPvbgBzIfhXetbZKpSxoowAQO/J1i5oRs90h24kjTd4qJd3qspxk1lhZcEC8IkfZXjNgjEQI=");
//
// OneDriveFolder folder = new OneDriveFolder(api, "PDF");
//
// for (OneDriveItem.Metadata metadata : OneDriveFolder.getRoot(api)) {
// System.out.println(metadata.getName());
// if (metadata.isFile()) {
// }
// }
//
// // for (OneDriveItem.Metadata search : OneDriveFolder.getRoot(api).search("index.html")) {
// // System.out.println(search.getName());
// // }
//
// // OneDriveFile file = new OneDriveFile(api, "key.txt");
// // System.out.println(file);
// }
// }

View File

@@ -0,0 +1,42 @@
package im.zhaojun.onedrive.controller;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
@Controller
public class OneDriveController {
@Resource
private RestTemplate restTemplate;
@GetMapping("/onedirve/callback")
@ResponseBody
public String onedriveCallback(String code, HttpServletRequest request) {
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8");
headers.setContentType(type);
headers.add("Accept", MediaType.APPLICATION_JSON.toString());
String json = "client_id=04a73532-6c16-4fe4-92e5-f2cd125ed553&redirect_uri=http://localhost:8080/onedirve/callback&client_secret=2gY/t?*Eff6i36TgKTtiG*08/k]@.I4[&code=" + code + "&grant_type=authorization_code";
HttpRequest post = HttpUtil.createPost("https://login.microsoftonline.com/common/oauth2/v2.0/token");
post.body(json, "application/x-www-form-urlencoded");
HttpResponse response = post.execute();
System.out.println(response.body());
return response.body();
}
}

View File

@@ -1,20 +1,21 @@
package im.zhaojun.qiniu.service;
import cn.hutool.core.util.URLUtil;
import com.qiniu.common.QiniuException;
import com.qiniu.common.Zone;
import com.qiniu.storage.BucketManager;
import com.qiniu.storage.Configuration;
import com.qiniu.storage.model.FileInfo;
import com.qiniu.storage.model.FileListing;
import com.qiniu.util.Auth;
import im.zhaojun.common.enums.FileTypeEnum;
import im.zhaojun.common.enums.StorageTypeEnum;
import im.zhaojun.common.model.FileItem;
import im.zhaojun.common.model.enums.FileTypeEnum;
import im.zhaojun.common.model.enums.StorageTypeEnum;
import im.zhaojun.common.model.dto.FileItemDTO;
import im.zhaojun.common.model.StorageConfig;
import im.zhaojun.common.service.FileService;
import im.zhaojun.common.service.StorageConfigService;
import im.zhaojun.common.util.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
@@ -25,7 +26,9 @@ import java.util.List;
import java.util.Map;
@Service
public class QiniuService implements FileService {
public class QiniuServiceImpl implements FileService {
private static final Logger log = LoggerFactory.getLogger(QiniuServiceImpl.class);
@Value("${zfile.cache.timeout}")
private Long timeout;
@@ -51,25 +54,33 @@ public class QiniuService implements FileService {
private boolean isPrivate;
public void initMethod() throws QiniuException {
Map<String, StorageConfig> stringStorageConfigMap =
storageConfigService.selectStorageConfigMapByKey(StorageTypeEnum.QINIU);
String accessKey = stringStorageConfigMap.get(ACCESS_KEY).getValue();
String secretKey = stringStorageConfigMap.get(SECRET_KEY).getValue();
private boolean isInitialized;
Configuration cfg = new Configuration(Zone.autoZone());
auth = Auth.create(accessKey, secretKey);
bucketManager = new BucketManager(auth, cfg);
bucketName = stringStorageConfigMap.get(BUCKET_NAME_KEY).getValue();
domain = stringStorageConfigMap.get(DOMAIN_KEY).getValue();
@Override
public void init() {
try {
Map<String, StorageConfig> stringStorageConfigMap =
storageConfigService.selectStorageConfigMapByKey(StorageTypeEnum.QINIU);
String accessKey = stringStorageConfigMap.get(ACCESS_KEY).getValue();
String secretKey = stringStorageConfigMap.get(SECRET_KEY).getValue();
isPrivate = bucketManager.getBucketInfo(bucketName).getPrivate() == 1;
Configuration cfg = new Configuration(Zone.autoZone());
auth = Auth.create(accessKey, secretKey);
bucketManager = new BucketManager(auth, cfg);
bucketName = stringStorageConfigMap.get(BUCKET_NAME_KEY).getValue();
domain = stringStorageConfigMap.get(DOMAIN_KEY).getValue();
isPrivate = bucketManager.getBucketInfo(bucketName).getPrivate() == 1;
isInitialized = true;
} catch (Exception e) {
log.debug(StorageTypeEnum.QINIU.getDescription() + "初始化异常, 已跳过");
}
}
@Override
public List<FileItem> fileList(String path) throws Exception {
public List<FileItemDTO> fileList(String path) throws Exception {
path = StringUtils.removeFirstSeparator(path);
List<FileItem> fileItemList = new ArrayList<>();
List<FileItemDTO> fileItemList = new ArrayList<>();
// 每次迭代的长度限制, 最大1000, 推荐值 1000
int limit = 1000;
@@ -81,23 +92,27 @@ public class QiniuService implements FileService {
String fileKey = item.key;
String fileName = fileKey.substring(path.length());
FileItem fileItem = new FileItem();
fileItem.setName(fileName);
fileItem.setSize(item.fsize);
fileItem.setTime(new Date(item.putTime / 1000));
fileItem.setType(FileTypeEnum.FILE);
fileItem.setPath(path);
fileItemList.add(fileItem);
FileItemDTO fileItemDTO = new FileItemDTO();
fileItemDTO.setName(fileName);
fileItemDTO.setSize(item.fsize);
fileItemDTO.setTime(new Date(item.putTime / 1000));
fileItemDTO.setType(FileTypeEnum.FILE);
fileItemDTO.setPath(path);
fileItemDTO.setUrl(getDownloadUrl(StringUtils.concatUrl(path, fileItemDTO.getName())));
fileItemList.add(fileItemDTO);
}
String[] commonPrefixes = fileListing.commonPrefixes;
for (String commonPrefix : commonPrefixes) {
FileItem fileItem = new FileItem();
fileItem.setName(commonPrefix.substring(0, commonPrefix.length() - 1));
fileItem.setType(FileTypeEnum.FOLDER);
fileItem.setPath(path);
fileItemList.add(fileItem);
if ("/".equals(commonPrefix)) {
continue;
}
FileItemDTO fileItemDTO = new FileItemDTO();
fileItemDTO.setName(commonPrefix.substring(0, commonPrefix.length() - 1));
fileItemDTO.setType(FileTypeEnum.FOLDER);
fileItemDTO.setPath(path);
fileItemList.add(fileItemDTO);
}
return fileItemList;
@@ -116,4 +131,11 @@ public class QiniuService implements FileService {
public StorageTypeEnum getStorageTypeEnum() {
return StorageTypeEnum.QINIU;
}
@Override
public boolean getIsInitialized() {
return isInitialized;
}
}

View File

@@ -1,110 +0,0 @@
package im.zhaojun.tencent;
import cn.hutool.core.util.URLUtil;
import com.qcloud.cos.COSClient;
import com.qcloud.cos.ClientConfig;
import com.qcloud.cos.auth.BasicCOSCredentials;
import com.qcloud.cos.auth.COSCredentials;
import com.qcloud.cos.model.COSObjectSummary;
import com.qcloud.cos.model.ListObjectsRequest;
import com.qcloud.cos.model.ObjectListing;
import com.qcloud.cos.region.Region;
import im.zhaojun.common.enums.FileTypeEnum;
import im.zhaojun.common.enums.StorageTypeEnum;
import im.zhaojun.common.model.FileItem;
import im.zhaojun.common.model.StorageConfig;
import im.zhaojun.common.service.FileService;
import im.zhaojun.common.service.StorageConfigService;
import im.zhaojun.common.util.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.net.URL;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
@Service
public class TencentService implements FileService {
@Resource
private StorageConfigService storageConfigService;
private static final String BUCKET_NAME_KEY = "bucket-name";
private static final String SECRET_ID_KEY = "secretId";
private static final String SECRET_KEY = "secretKey";
private static final String DOMAIN_KEY = "domain";
private static final String ENDPOINT_KEY = "endPoint";
@Value("${zfile.cache.timeout}")
private Long timeout;
private String bucketName;
private String domain;
private COSClient cosClient;
@Override
public void initMethod() {
Map<String, StorageConfig> stringStorageConfigMap =
storageConfigService.selectStorageConfigMapByKey(StorageTypeEnum.TENCENT);
String secretId = stringStorageConfigMap.get(SECRET_ID_KEY).getValue();
String secretKey = stringStorageConfigMap.get(SECRET_KEY).getValue();
String endPoint = stringStorageConfigMap.get(ENDPOINT_KEY).getValue();
bucketName = stringStorageConfigMap.get(BUCKET_NAME_KEY).getValue();
domain = stringStorageConfigMap.get(DOMAIN_KEY).getValue();
COSCredentials cred = new BasicCOSCredentials(secretId, secretKey);
Region region = new Region("ap-shanghai");
ClientConfig clientConfig = new ClientConfig(region);
// clientConfig.setSignExpired();
cosClient = new COSClient(cred, clientConfig);
}
@Override
public List<FileItem> fileList(String path) {
path = StringUtils.removeFirstSeparator(path);
List<FileItem> fileItemList = new ArrayList<>();
ObjectListing objectListing = cosClient.listObjects(new ListObjectsRequest().withBucketName(bucketName).withDelimiter("/").withPrefix(path));
for (COSObjectSummary s : objectListing.getObjectSummaries()) {
FileItem fileItem = new FileItem();
fileItem.setName(s.getKey().substring(path.length()));
fileItem.setSize(s.getSize());
fileItem.setTime(s.getLastModified());
fileItem.setType(FileTypeEnum.FILE);
fileItem.setPath(path);
fileItemList.add(fileItem);
}
for (String commonPrefix : objectListing.getCommonPrefixes()) {
FileItem fileItem = new FileItem();
fileItem.setName(commonPrefix.substring(path.length(), commonPrefix.length() - 1));
fileItem.setType(FileTypeEnum.FOLDER);
fileItem.setPath(path);
fileItemList.add(fileItem);
}
return fileItemList;
}
@Override
public String getDownloadUrl(String path) {
Date expirationDate = new Date(new Date().getTime() + timeout * 1000);
URL url = cosClient.generatePresignedUrl(bucketName, path, expirationDate);
return URLUtil.complateUrl(domain, url.getFile());
}
@Override
public StorageTypeEnum getStorageTypeEnum() {
return StorageTypeEnum.TENCENT;
}
}

View File

@@ -0,0 +1,128 @@
package im.zhaojun.tencent;
import cn.hutool.core.util.URLUtil;
import com.qcloud.cos.COSClient;
import com.qcloud.cos.ClientConfig;
import com.qcloud.cos.auth.BasicCOSCredentials;
import com.qcloud.cos.auth.COSCredentials;
import com.qcloud.cos.model.COSObjectSummary;
import com.qcloud.cos.model.ListObjectsRequest;
import com.qcloud.cos.model.ObjectListing;
import com.qcloud.cos.region.Region;
import im.zhaojun.common.model.enums.FileTypeEnum;
import im.zhaojun.common.model.enums.StorageTypeEnum;
import im.zhaojun.common.model.dto.FileItemDTO;
import im.zhaojun.common.model.StorageConfig;
import im.zhaojun.common.service.FileService;
import im.zhaojun.common.service.StorageConfigService;
import im.zhaojun.common.util.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.net.URL;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
@Service
public class TencentServiceImpl implements FileService {
private static final Logger log = LoggerFactory.getLogger(TencentServiceImpl.class);
@Resource
private StorageConfigService storageConfigService;
private static final String BUCKET_NAME_KEY = "bucket-name";
private static final String SECRET_ID_KEY = "secretId";
private static final String SECRET_KEY = "secretKey";
private static final String DOMAIN_KEY = "domain";
private static final String ENDPOINT_KEY = "endPoint";
@Value("${zfile.cache.timeout}")
private Long timeout;
private String bucketName;
private String domain;
private COSClient cosClient;
private boolean isInitialized;
@Override
public void init() {
try {
Map<String, StorageConfig> stringStorageConfigMap =
storageConfigService.selectStorageConfigMapByKey(StorageTypeEnum.TENCENT);
String secretId = stringStorageConfigMap.get(SECRET_ID_KEY).getValue();
String secretKey = stringStorageConfigMap.get(SECRET_KEY).getValue();
String regionName = stringStorageConfigMap.get(ENDPOINT_KEY).getValue();
bucketName = stringStorageConfigMap.get(BUCKET_NAME_KEY).getValue();
domain = stringStorageConfigMap.get(DOMAIN_KEY).getValue();
COSCredentials cred = new BasicCOSCredentials(secretId, secretKey);
Region region = new Region(regionName);
ClientConfig clientConfig = new ClientConfig(region);
cosClient = new COSClient(cred, clientConfig);
isInitialized = true;
} catch (Exception e) {
log.debug(StorageTypeEnum.TENCENT.getDescription() + "初始化异常, 已跳过");
}
}
@Override
public List<FileItemDTO> fileList(String path) {
path = StringUtils.removeFirstSeparator(path);
List<FileItemDTO> fileItemList = new ArrayList<>();
ObjectListing objectListing = cosClient.listObjects(new ListObjectsRequest().withBucketName(bucketName).withDelimiter("/").withPrefix(path));
for (COSObjectSummary s : objectListing.getObjectSummaries()) {
FileItemDTO fileItemDTO = new FileItemDTO();
fileItemDTO.setName(s.getKey().substring(path.length()));
fileItemDTO.setSize(s.getSize());
fileItemDTO.setTime(s.getLastModified());
fileItemDTO.setType(FileTypeEnum.FILE);
fileItemDTO.setPath(path);
fileItemDTO.setUrl(getDownloadUrl(StringUtils.concatUrl(path, fileItemDTO.getName())));
fileItemList.add(fileItemDTO);
}
for (String commonPrefix : objectListing.getCommonPrefixes()) {
FileItemDTO fileItemDTO = new FileItemDTO();
fileItemDTO.setName(commonPrefix.substring(path.length(), commonPrefix.length() - 1));
fileItemDTO.setType(FileTypeEnum.FOLDER);
fileItemDTO.setPath(path);
fileItemList.add(fileItemDTO);
}
return fileItemList;
}
@Override
public String getDownloadUrl(String path) {
Date expirationDate = new Date(System.currentTimeMillis() + timeout * 1000);
URL url = cosClient.generatePresignedUrl(bucketName, path, expirationDate);
return URLUtil.complateUrl(domain, url.getFile());
}
@Override
public StorageTypeEnum getStorageTypeEnum() {
return StorageTypeEnum.TENCENT;
}
@Override
public boolean getIsInitialized() {
return isInitialized;
}
}

View File

@@ -1,89 +0,0 @@
package im.zhaojun.upyun.service;
import cn.hutool.core.util.URLUtil;
import com.UpYun;
import im.zhaojun.common.enums.FileTypeEnum;
import im.zhaojun.common.enums.StorageTypeEnum;
import im.zhaojun.common.model.FileItem;
import im.zhaojun.common.model.StorageConfig;
import im.zhaojun.common.service.FileService;
import im.zhaojun.common.service.StorageConfigService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Service
public class UpYunService implements FileService {
@Resource
private StorageConfigService storageConfigService;
private static final String BUCKET_NAME_KEY = "bucket-name";
private static final String USERNAME_KEY = "username";
private static final String PASSWORD_KEY = "password";
private static final String DOMAIN_KEY = "domain";
private String domain;
private UpYun upYun;
public void initMethod() {
Map<String, StorageConfig> stringStorageConfigMap =
storageConfigService.selectStorageConfigMapByKey(StorageTypeEnum.UPYUN);
String bucketName = stringStorageConfigMap.get(BUCKET_NAME_KEY).getValue();
String username = stringStorageConfigMap.get(USERNAME_KEY).getValue();
String password = stringStorageConfigMap.get(PASSWORD_KEY).getValue();
domain = stringStorageConfigMap.get(DOMAIN_KEY).getValue();
upYun = new UpYun(bucketName, username, password);
}
@Override
public List<FileItem> fileList(String path) throws Exception {
ArrayList<FileItem> fileItems = new ArrayList<>();
String nextMark = null;
do {
HashMap<String, String> hashMap = new HashMap<>();
hashMap.put("x-list-iter", nextMark);
hashMap.put("x-list-limit", "100");
UpYun.FolderItemIter folderItemIter = upYun.readDirIter(URLUtil.encode(path), hashMap);
nextMark = folderItemIter.iter;
ArrayList<UpYun.FolderItem> folderItems = folderItemIter.files;
if (folderItems != null) {
for (UpYun.FolderItem folderItem : folderItems) {
FileItem fileItem = new FileItem();
fileItem.setName(folderItem.name);
fileItem.setSize(folderItem.size);
fileItem.setTime(folderItem.date);
fileItem.setPath(path);
if ("folder".equals(folderItem.type)) {
fileItem.setType(FileTypeEnum.FOLDER);
} else {
fileItem.setType(FileTypeEnum.FILE);
}
fileItems.add(fileItem);
}
}
} while (!"g2gCZAAEbmV4dGQAA2VvZg".equals(nextMark));
return fileItems;
}
@Override
public String getDownloadUrl(String path) {
return URLUtil.complateUrl(domain, path);
}
@Override
public StorageTypeEnum getStorageTypeEnum() {
return StorageTypeEnum.UPYUN;
}
}

View File

@@ -0,0 +1,111 @@
package im.zhaojun.upyun.service;
import cn.hutool.core.util.URLUtil;
import com.UpYun;
import im.zhaojun.common.model.enums.FileTypeEnum;
import im.zhaojun.common.model.enums.StorageTypeEnum;
import im.zhaojun.common.model.dto.FileItemDTO;
import im.zhaojun.common.model.StorageConfig;
import im.zhaojun.common.service.FileService;
import im.zhaojun.common.service.StorageConfigService;
import im.zhaojun.common.util.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Service
public class UpYunServiceImpl implements FileService {
private static final Logger log = LoggerFactory.getLogger(UpYunServiceImpl.class);
@Resource
private StorageConfigService storageConfigService;
private static final String BUCKET_NAME_KEY = "bucket-name";
private static final String USERNAME_KEY = "username";
private static final String PASSWORD_KEY = "password";
private static final String DOMAIN_KEY = "domain";
private String domain;
private UpYun upYun;
private boolean isInitialized;
@Override
public void init() {
try {
Map<String, StorageConfig> stringStorageConfigMap =
storageConfigService.selectStorageConfigMapByKey(StorageTypeEnum.UPYUN);
String bucketName = stringStorageConfigMap.get(BUCKET_NAME_KEY).getValue();
String username = stringStorageConfigMap.get(USERNAME_KEY).getValue();
String password = stringStorageConfigMap.get(PASSWORD_KEY).getValue();
domain = stringStorageConfigMap.get(DOMAIN_KEY).getValue();
upYun = new UpYun(bucketName, username, password);
isInitialized = true;
} catch (Exception e) {
log.debug(StorageTypeEnum.UPYUN.getDescription() + "初始化异常, 已跳过");
}
}
@Override
public List<FileItemDTO> fileList(String path) throws Exception {
ArrayList<FileItemDTO> fileItemList = new ArrayList<>();
String nextMark = null;
do {
HashMap<String, String> hashMap = new HashMap<>(24);
hashMap.put("x-list-iter", nextMark);
hashMap.put("x-list-limit", "100");
UpYun.FolderItemIter folderItemIter = upYun.readDirIter(URLUtil.encode(path), hashMap);
nextMark = folderItemIter.iter;
ArrayList<UpYun.FolderItem> folderItems = folderItemIter.files;
if (folderItems != null) {
for (UpYun.FolderItem folderItem : folderItems) {
FileItemDTO fileItemDTO = new FileItemDTO();
fileItemDTO.setName(folderItem.name);
fileItemDTO.setSize(folderItem.size);
fileItemDTO.setTime(folderItem.date);
fileItemDTO.setPath(path);
if ("folder".equals(folderItem.type)) {
fileItemDTO.setType(FileTypeEnum.FOLDER);
} else {
fileItemDTO.setType(FileTypeEnum.FILE);
fileItemDTO.setUrl(getDownloadUrl(StringUtils.concatUrl(path, fileItemDTO.getName())));
}
fileItemList.add(fileItemDTO);
}
}
} while (!"g2gCZAAEbmV4dGQAA2VvZg".equals(nextMark));
return fileItemList;
}
@Override
public String getDownloadUrl(String path) {
return URLUtil.complateUrl(domain, path);
}
@Override
public StorageTypeEnum getStorageTypeEnum() {
return StorageTypeEnum.UPYUN;
}
@Override
public boolean getIsInitialized() {
return isInitialized;
}
}