mirror of https://github.com/halo-dev/halo
feat: provide static mapping feature (#710)
* Provide static mapping feature * feat: filter inner mapping for static storage.pull/711/head
parent
2792d11cd2
commit
bc75275815
|
@ -34,7 +34,7 @@ public class InMemoryCacheStore extends AbstractStringCacheStore {
|
||||||
/**
|
/**
|
||||||
* Lock.
|
* Lock.
|
||||||
*/
|
*/
|
||||||
private Lock lock = new ReentrantLock();
|
private final Lock lock = new ReentrantLock();
|
||||||
|
|
||||||
public InMemoryCacheStore() {
|
public InMemoryCacheStore() {
|
||||||
// Run a cache store cleaner
|
// Run a cache store cleaner
|
||||||
|
|
|
@ -0,0 +1,96 @@
|
||||||
|
package run.halo.app.config;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.context.ApplicationListener;
|
||||||
|
import org.springframework.util.AntPathMatcher;
|
||||||
|
import org.springframework.util.PathMatcher;
|
||||||
|
import org.springframework.web.method.HandlerMethod;
|
||||||
|
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
|
||||||
|
import run.halo.app.config.properties.HaloProperties;
|
||||||
|
import run.halo.app.event.StaticStorageChangedEvent;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import static run.halo.app.utils.HaloUtils.URL_SEPARATOR;
|
||||||
|
import static run.halo.app.utils.HaloUtils.ensureBoth;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author ryanwang
|
||||||
|
* @date 2020-03-24
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class HaloRequestMappingHandlerMapping extends RequestMappingHandlerMapping implements ApplicationListener<StaticStorageChangedEvent> {
|
||||||
|
|
||||||
|
private final Set<String> blackPatterns = new HashSet<>(16);
|
||||||
|
|
||||||
|
private final PathMatcher pathMatcher;
|
||||||
|
|
||||||
|
private final HaloProperties haloProperties;
|
||||||
|
|
||||||
|
public HaloRequestMappingHandlerMapping(HaloProperties haloProperties) {
|
||||||
|
this.haloProperties = haloProperties;
|
||||||
|
this.initBlackPatterns();
|
||||||
|
pathMatcher = new AntPathMatcher();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
|
||||||
|
log.debug("Looking path: [{}]", lookupPath);
|
||||||
|
for (String blackPattern : blackPatterns) {
|
||||||
|
if (this.pathMatcher.match(blackPattern, lookupPath)) {
|
||||||
|
log.debug("Skipped path [{}] with pattern: [{}]", lookupPath, blackPattern);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return super.lookupHandlerMethod(lookupPath, request);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initBlackPatterns() {
|
||||||
|
String uploadUrlPattern = ensureBoth(haloProperties.getUploadUrlPrefix(), URL_SEPARATOR) + "**";
|
||||||
|
String adminPathPattern = ensureBoth(haloProperties.getAdminPath(), URL_SEPARATOR) + "?*/**";
|
||||||
|
|
||||||
|
blackPatterns.add("/themes/**");
|
||||||
|
blackPatterns.add("/js/**");
|
||||||
|
blackPatterns.add("/images/**");
|
||||||
|
blackPatterns.add("/fonts/**");
|
||||||
|
blackPatterns.add("/css/**");
|
||||||
|
blackPatterns.add("/assets/**");
|
||||||
|
blackPatterns.add("/color.less");
|
||||||
|
blackPatterns.add("/swagger-ui.html");
|
||||||
|
blackPatterns.add("/csrf");
|
||||||
|
blackPatterns.add("/webjars/**");
|
||||||
|
blackPatterns.add(uploadUrlPattern);
|
||||||
|
blackPatterns.add(adminPathPattern);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onApplicationEvent(StaticStorageChangedEvent event) {
|
||||||
|
Path staticPath = event.getStaticPath();
|
||||||
|
try (Stream<Path> rootPathStream = Files.list(staticPath)) {
|
||||||
|
synchronized (this) {
|
||||||
|
blackPatterns.clear();
|
||||||
|
initBlackPatterns();
|
||||||
|
rootPathStream.forEach(rootPath -> {
|
||||||
|
if (Files.isDirectory(rootPath)) {
|
||||||
|
String directoryPattern = "/" + rootPath.getFileName().toString() + "/**";
|
||||||
|
blackPatterns.add(directoryPattern);
|
||||||
|
log.debug("Exclude for folder path pattern: [{}]", directoryPattern);
|
||||||
|
} else {
|
||||||
|
String pathPattern = "/" + rootPath.getFileName().toString();
|
||||||
|
blackPatterns.add(pathPattern);
|
||||||
|
log.debug("Exclude for file path pattern: [{}]", pathPattern);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.error("Failed to refresh static directory mapping", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,9 +17,6 @@ import org.springframework.format.FormatterRegistry;
|
||||||
import org.springframework.http.converter.HttpMessageConverter;
|
import org.springframework.http.converter.HttpMessageConverter;
|
||||||
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
|
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
|
||||||
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
|
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
|
||||||
import org.springframework.util.AntPathMatcher;
|
|
||||||
import org.springframework.util.PathMatcher;
|
|
||||||
import org.springframework.web.method.HandlerMethod;
|
|
||||||
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
|
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
|
||||||
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
|
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
|
||||||
import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
|
import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
|
||||||
|
@ -33,12 +30,9 @@ import run.halo.app.factory.StringToEnumConverterFactory;
|
||||||
import run.halo.app.model.support.HaloConst;
|
import run.halo.app.model.support.HaloConst;
|
||||||
import run.halo.app.security.resolver.AuthenticationArgumentResolver;
|
import run.halo.app.security.resolver.AuthenticationArgumentResolver;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import static run.halo.app.model.support.HaloConst.FILE_SEPARATOR;
|
import static run.halo.app.model.support.HaloConst.FILE_SEPARATOR;
|
||||||
import static run.halo.app.utils.HaloUtils.*;
|
import static run.halo.app.utils.HaloUtils.*;
|
||||||
|
@ -188,48 +182,4 @@ public class WebMvcAutoConfiguration extends WebMvcConfigurationSupport {
|
||||||
return new HaloRequestMappingHandlerMapping(haloProperties);
|
return new HaloRequestMappingHandlerMapping(haloProperties);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class HaloRequestMappingHandlerMapping extends RequestMappingHandlerMapping {
|
|
||||||
|
|
||||||
private final Set<String> blackPatterns = new HashSet<>(16);
|
|
||||||
|
|
||||||
private final PathMatcher pathMatcher;
|
|
||||||
|
|
||||||
private final HaloProperties haloProperties;
|
|
||||||
|
|
||||||
public HaloRequestMappingHandlerMapping(HaloProperties haloProperties) {
|
|
||||||
this.haloProperties = haloProperties;
|
|
||||||
this.initBlackPatterns();
|
|
||||||
pathMatcher = new AntPathMatcher();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
|
|
||||||
log.debug("Looking path: [{}]", lookupPath);
|
|
||||||
for (String blackPattern : blackPatterns) {
|
|
||||||
if (this.pathMatcher.match(blackPattern, lookupPath)) {
|
|
||||||
log.debug("Skipped path [{}] with pattern: [{}]", lookupPath, blackPattern);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return super.lookupHandlerMethod(lookupPath, request);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void initBlackPatterns() {
|
|
||||||
String uploadUrlPattern = ensureBoth(haloProperties.getUploadUrlPrefix(), URL_SEPARATOR) + "**";
|
|
||||||
String adminPathPattern = ensureBoth(haloProperties.getAdminPath(), URL_SEPARATOR) + "?*/**";
|
|
||||||
|
|
||||||
blackPatterns.add("/themes/**");
|
|
||||||
blackPatterns.add("/js/**");
|
|
||||||
blackPatterns.add("/images/**");
|
|
||||||
blackPatterns.add("/fonts/**");
|
|
||||||
blackPatterns.add("/css/**");
|
|
||||||
blackPatterns.add("/assets/**");
|
|
||||||
blackPatterns.add("/color.less");
|
|
||||||
blackPatterns.add("/swagger-ui.html");
|
|
||||||
blackPatterns.add("/csrf");
|
|
||||||
blackPatterns.add("/webjars/**");
|
|
||||||
blackPatterns.add(uploadUrlPattern);
|
|
||||||
blackPatterns.add(adminPathPattern);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,6 +47,6 @@ public class StaticStorageController {
|
||||||
@ApiOperation("Uploads static file")
|
@ApiOperation("Uploads static file")
|
||||||
public void upload(String basePath,
|
public void upload(String basePath,
|
||||||
@RequestPart("file") MultipartFile file) {
|
@RequestPart("file") MultipartFile file) {
|
||||||
staticStorageService.update(basePath, file);
|
staticStorageService.upload(basePath, file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
package run.halo.app.event;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import org.springframework.context.ApplicationEvent;
|
||||||
|
|
||||||
|
import java.nio.file.Path;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author ryanwang
|
||||||
|
* @date 2020-03-24
|
||||||
|
*/
|
||||||
|
public class StaticStorageChangedEvent extends ApplicationEvent {
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private final Path staticPath;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new {@code ApplicationEvent}.
|
||||||
|
*
|
||||||
|
* @param source the object on which the event initially occurred or with
|
||||||
|
* which the event is associated (never {@code null})
|
||||||
|
*/
|
||||||
|
public StaticStorageChangedEvent(Object source, Path staticPath) {
|
||||||
|
super(source);
|
||||||
|
this.staticPath = staticPath;
|
||||||
|
}
|
||||||
|
}
|
|
@ -20,7 +20,7 @@ public class StringToEnumConverterFactory implements ConverterFactory<String, En
|
||||||
private static class StringToEnumConverter<T extends Enum>
|
private static class StringToEnumConverter<T extends Enum>
|
||||||
implements Converter<String, T> {
|
implements Converter<String, T> {
|
||||||
|
|
||||||
private Class<T> enumType;
|
private final Class<T> enumType;
|
||||||
|
|
||||||
private StringToEnumConverter(Class<T> enumType) {
|
private StringToEnumConverter(Class<T> enumType) {
|
||||||
this.enumType = enumType;
|
this.enumType = enumType;
|
||||||
|
|
|
@ -54,7 +54,7 @@ public class SmmsFileHandler implements FileHandler {
|
||||||
|
|
||||||
private final OptionService optionService;
|
private final OptionService optionService;
|
||||||
|
|
||||||
private HttpHeaders headers = new HttpHeaders();
|
private final HttpHeaders headers = new HttpHeaders();
|
||||||
|
|
||||||
public SmmsFileHandler(RestTemplate httpsRestTemplate,
|
public SmmsFileHandler(RestTemplate httpsRestTemplate,
|
||||||
OptionService optionService) {
|
OptionService optionService) {
|
||||||
|
|
|
@ -43,7 +43,7 @@ public enum AttachmentType implements ValueEnum<Integer> {
|
||||||
*/
|
*/
|
||||||
TENCENTCOS(6);
|
TENCENTCOS(6);
|
||||||
|
|
||||||
private Integer value;
|
private final Integer value;
|
||||||
|
|
||||||
AttachmentType(Integer value) {
|
AttachmentType(Integer value) {
|
||||||
this.value = value;
|
this.value = value;
|
||||||
|
|
|
@ -15,7 +15,7 @@ public enum BanStatusEnum {
|
||||||
*/
|
*/
|
||||||
NORMAL(0);
|
NORMAL(0);
|
||||||
|
|
||||||
private int status;
|
private final int status;
|
||||||
|
|
||||||
BanStatusEnum(int status) {
|
BanStatusEnum(int status) {
|
||||||
this.status = status;
|
this.status = status;
|
||||||
|
|
|
@ -19,7 +19,7 @@ public enum CommentViolationTypeEnum {
|
||||||
*/
|
*/
|
||||||
FREQUENTLY(1);
|
FREQUENTLY(1);
|
||||||
|
|
||||||
private int type;
|
private final int type;
|
||||||
|
|
||||||
CommentViolationTypeEnum(int type) {
|
CommentViolationTypeEnum(int type) {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
|
|
|
@ -23,7 +23,7 @@ public enum DataType implements ValueEnum<Integer> {
|
||||||
|
|
||||||
BOOL(3);
|
BOOL(3);
|
||||||
|
|
||||||
private Integer value;
|
private final Integer value;
|
||||||
|
|
||||||
DataType(Integer value) {
|
DataType(Integer value) {
|
||||||
this.value = value;
|
this.value = value;
|
||||||
|
|
|
@ -18,7 +18,7 @@ public enum GlobalPathType implements ValueEnum<Integer> {
|
||||||
*/
|
*/
|
||||||
ABSOLUTE(1);
|
ABSOLUTE(1);
|
||||||
|
|
||||||
private Integer value;
|
private final Integer value;
|
||||||
|
|
||||||
GlobalPathType(Integer value) {
|
GlobalPathType(Integer value) {
|
||||||
this.value = value;
|
this.value = value;
|
||||||
|
|
|
@ -23,7 +23,7 @@ public enum MigrateType implements ValueEnum<Integer> {
|
||||||
*/
|
*/
|
||||||
CNBLOGS(2);
|
CNBLOGS(2);
|
||||||
|
|
||||||
private Integer value;
|
private final Integer value;
|
||||||
|
|
||||||
MigrateType(Integer value) {
|
MigrateType(Integer value) {
|
||||||
this.value = value;
|
this.value = value;
|
||||||
|
|
|
@ -18,7 +18,7 @@ public enum OptionType implements ValueEnum<Integer> {
|
||||||
*/
|
*/
|
||||||
CUSTOM(1);
|
CUSTOM(1);
|
||||||
|
|
||||||
private Integer value;
|
private final Integer value;
|
||||||
|
|
||||||
OptionType(Integer value) {
|
OptionType(Integer value) {
|
||||||
this.value = value;
|
this.value = value;
|
||||||
|
|
|
@ -16,7 +16,7 @@ public enum PostEditorType implements ValueEnum<Integer> {
|
||||||
*/
|
*/
|
||||||
RICHTEXT(1);
|
RICHTEXT(1);
|
||||||
|
|
||||||
private Integer value;
|
private final Integer value;
|
||||||
|
|
||||||
PostEditorType(Integer value) {
|
PostEditorType(Integer value) {
|
||||||
this.value = value;
|
this.value = value;
|
||||||
|
|
|
@ -28,7 +28,7 @@ public enum PostPermalinkType implements ValueEnum<Integer> {
|
||||||
*/
|
*/
|
||||||
ID(3);
|
ID(3);
|
||||||
|
|
||||||
private Integer value;
|
private final Integer value;
|
||||||
|
|
||||||
PostPermalinkType(Integer value) {
|
PostPermalinkType(Integer value) {
|
||||||
this.value = value;
|
this.value = value;
|
||||||
|
|
|
@ -18,7 +18,7 @@ public enum StaticDeployType implements ValueEnum<Integer> {
|
||||||
*/
|
*/
|
||||||
NETLIFY(1);
|
NETLIFY(1);
|
||||||
|
|
||||||
private Integer value;
|
private final Integer value;
|
||||||
|
|
||||||
StaticDeployType(Integer value) {
|
StaticDeployType(Integer value) {
|
||||||
this.value = value;
|
this.value = value;
|
||||||
|
|
|
@ -52,8 +52,8 @@ public enum UpOssProperties implements PropertyEnum {
|
||||||
OSS_THUMBNAIL_STYLE_RULE("oss_upyun_thumbnail_style_rule", String.class, "");
|
OSS_THUMBNAIL_STYLE_RULE("oss_upyun_thumbnail_style_rule", String.class, "");
|
||||||
|
|
||||||
private final String defaultValue;
|
private final String defaultValue;
|
||||||
private String value;
|
private final String value;
|
||||||
private Class<?> type;
|
private final Class<?> type;
|
||||||
|
|
||||||
UpOssProperties(String value, Class<?> type, String defaultValue) {
|
UpOssProperties(String value, Class<?> type, String defaultValue) {
|
||||||
this.defaultValue = defaultValue;
|
this.defaultValue = defaultValue;
|
||||||
|
|
|
@ -46,7 +46,7 @@ public abstract class AbstractAuthenticationFilter extends OncePerRequestFilter
|
||||||
protected final OptionService optionService;
|
protected final OptionService optionService;
|
||||||
protected final AbstractStringCacheStore cacheStore;
|
protected final AbstractStringCacheStore cacheStore;
|
||||||
private final UrlPathHelper urlPathHelper = new UrlPathHelper();
|
private final UrlPathHelper urlPathHelper = new UrlPathHelper();
|
||||||
private OneTimeTokenService oneTimeTokenService;
|
private final OneTimeTokenService oneTimeTokenService;
|
||||||
|
|
||||||
private volatile AuthenticationFailureHandler failureHandler;
|
private volatile AuthenticationFailureHandler failureHandler;
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -14,6 +14,8 @@ import java.util.List;
|
||||||
*/
|
*/
|
||||||
public interface StaticStorageService {
|
public interface StaticStorageService {
|
||||||
|
|
||||||
|
String API_FOLDER_NAME = "api";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Static folder location.
|
* Static folder location.
|
||||||
*/
|
*/
|
||||||
|
@ -47,5 +49,5 @@ public interface StaticStorageService {
|
||||||
* @param basePath base path
|
* @param basePath base path
|
||||||
* @param file file must not be null.
|
* @param file file must not be null.
|
||||||
*/
|
*/
|
||||||
void update(String basePath, @NonNull MultipartFile file);
|
void upload(String basePath, @NonNull MultipartFile file);
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,7 +54,7 @@ public class OptionServiceImpl extends AbstractCrudService<Option, Integer> impl
|
||||||
private final AbstractStringCacheStore cacheStore;
|
private final AbstractStringCacheStore cacheStore;
|
||||||
private final Map<String, PropertyEnum> propertyEnumMap;
|
private final Map<String, PropertyEnum> propertyEnumMap;
|
||||||
private final ApplicationEventPublisher eventPublisher;
|
private final ApplicationEventPublisher eventPublisher;
|
||||||
private HaloProperties haloProperties;
|
private final HaloProperties haloProperties;
|
||||||
|
|
||||||
public OptionServiceImpl(HaloProperties haloProperties,
|
public OptionServiceImpl(HaloProperties haloProperties,
|
||||||
OptionRepository optionRepository,
|
OptionRepository optionRepository,
|
||||||
|
|
|
@ -3,12 +3,16 @@ package run.halo.app.service.impl;
|
||||||
import cn.hutool.core.util.IdUtil;
|
import cn.hutool.core.util.IdUtil;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.springframework.boot.context.event.ApplicationStartedEvent;
|
||||||
|
import org.springframework.context.ApplicationEventPublisher;
|
||||||
|
import org.springframework.context.ApplicationListener;
|
||||||
import org.springframework.lang.NonNull;
|
import org.springframework.lang.NonNull;
|
||||||
import org.springframework.lang.Nullable;
|
import org.springframework.lang.Nullable;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
import run.halo.app.config.properties.HaloProperties;
|
import run.halo.app.config.properties.HaloProperties;
|
||||||
|
import run.halo.app.event.StaticStorageChangedEvent;
|
||||||
import run.halo.app.exception.FileOperationException;
|
import run.halo.app.exception.FileOperationException;
|
||||||
import run.halo.app.exception.ServiceException;
|
import run.halo.app.exception.ServiceException;
|
||||||
import run.halo.app.model.support.StaticFile;
|
import run.halo.app.model.support.StaticFile;
|
||||||
|
@ -32,16 +36,17 @@ import java.util.stream.Stream;
|
||||||
*/
|
*/
|
||||||
@Service
|
@Service
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class StaticStorageServiceImpl implements StaticStorageService {
|
public class StaticStorageServiceImpl implements StaticStorageService, ApplicationListener<ApplicationStartedEvent> {
|
||||||
|
|
||||||
private final Path staticDir;
|
private final Path staticDir;
|
||||||
|
|
||||||
private final HaloProperties haloProperties;
|
private final ApplicationEventPublisher eventPublisher;
|
||||||
|
|
||||||
public StaticStorageServiceImpl(HaloProperties haloProperties) throws IOException {
|
public StaticStorageServiceImpl(HaloProperties haloProperties,
|
||||||
|
ApplicationEventPublisher eventPublisher) throws IOException {
|
||||||
staticDir = Paths.get(haloProperties.getWorkDir(), STATIC_FOLDER);
|
staticDir = Paths.get(haloProperties.getWorkDir(), STATIC_FOLDER);
|
||||||
|
this.eventPublisher = eventPublisher;
|
||||||
FileUtils.createIfAbsent(staticDir);
|
FileUtils.createIfAbsent(staticDir);
|
||||||
this.haloProperties = haloProperties;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -100,6 +105,7 @@ public class StaticStorageServiceImpl implements StaticStorageService {
|
||||||
} else {
|
} else {
|
||||||
Files.deleteIfExists(path);
|
Files.deleteIfExists(path);
|
||||||
}
|
}
|
||||||
|
onChange();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new FileOperationException("文件 " + relativePath + " 删除失败", e);
|
throw new FileOperationException("文件 " + relativePath + " 删除失败", e);
|
||||||
}
|
}
|
||||||
|
@ -111,6 +117,10 @@ public class StaticStorageServiceImpl implements StaticStorageService {
|
||||||
|
|
||||||
Path path;
|
Path path;
|
||||||
|
|
||||||
|
if (StringUtils.startsWith(folderName, API_FOLDER_NAME)) {
|
||||||
|
throw new FileOperationException("目录名称 " + folderName + " 不合法");
|
||||||
|
}
|
||||||
|
|
||||||
if (StringUtils.isEmpty(basePath)) {
|
if (StringUtils.isEmpty(basePath)) {
|
||||||
path = Paths.get(staticDir.toString(), folderName);
|
path = Paths.get(staticDir.toString(), folderName);
|
||||||
} else {
|
} else {
|
||||||
|
@ -129,11 +139,15 @@ public class StaticStorageServiceImpl implements StaticStorageService {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update(String basePath, MultipartFile file) {
|
public void upload(String basePath, MultipartFile file) {
|
||||||
Assert.notNull(file, "Multipart file must not be null");
|
Assert.notNull(file, "Multipart file must not be null");
|
||||||
|
|
||||||
Path uploadPath;
|
Path uploadPath;
|
||||||
|
|
||||||
|
if (StringUtils.startsWith(file.getOriginalFilename(), API_FOLDER_NAME)) {
|
||||||
|
throw new FileOperationException("文件名称 " + file.getOriginalFilename() + " 不合法");
|
||||||
|
}
|
||||||
|
|
||||||
if (StringUtils.isEmpty(basePath)) {
|
if (StringUtils.isEmpty(basePath)) {
|
||||||
uploadPath = Paths.get(staticDir.toString(), file.getOriginalFilename());
|
uploadPath = Paths.get(staticDir.toString(), file.getOriginalFilename());
|
||||||
} else {
|
} else {
|
||||||
|
@ -147,8 +161,18 @@ public class StaticStorageServiceImpl implements StaticStorageService {
|
||||||
try {
|
try {
|
||||||
Files.createFile(uploadPath);
|
Files.createFile(uploadPath);
|
||||||
file.transferTo(uploadPath);
|
file.transferTo(uploadPath);
|
||||||
|
onChange();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new ServiceException("上传文件失败").setErrorData(uploadPath);
|
throw new ServiceException("上传文件失败").setErrorData(uploadPath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void onChange() {
|
||||||
|
eventPublisher.publishEvent(new StaticStorageChangedEvent(this, staticDir));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onApplicationEvent(ApplicationStartedEvent event) {
|
||||||
|
onChange();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue