mirror of https://github.com/halo-dev/halo
Make more friendly error track (#1191)
* Update gradle wrapper version to 6.6.1 * Upgrade h2 version to 1.4.197 * Make controller log more details * Refactor FileHandler * Fix image reader errorpull/1203/head
parent
9951a83ad6
commit
6fb65d0128
|
@ -60,7 +60,7 @@ ext {
|
||||||
thumbnailatorVersion = "0.4.11"
|
thumbnailatorVersion = "0.4.11"
|
||||||
image4jVersion = "0.7zensight1"
|
image4jVersion = "0.7zensight1"
|
||||||
flywayVersion = "6.5.0"
|
flywayVersion = "6.5.0"
|
||||||
h2Version = "1.4.196"
|
h2Version = "1.4.197"
|
||||||
levelDbVersion = "0.12"
|
levelDbVersion = "0.12"
|
||||||
annotationsVersion = "3.0.1u2"
|
annotationsVersion = "3.0.1u2"
|
||||||
zxingVersion = "3.4.0"
|
zxingVersion = "3.4.0"
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-all.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-6.6.1-bin.zip
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package run.halo.app.controller.core;
|
package run.halo.app.controller.core;
|
||||||
|
|
||||||
import cn.hutool.extra.servlet.ServletUtil;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.boot.autoconfigure.web.ErrorProperties;
|
import org.springframework.boot.autoconfigure.web.ErrorProperties;
|
||||||
import org.springframework.boot.autoconfigure.web.ServerProperties;
|
import org.springframework.boot.autoconfigure.web.ServerProperties;
|
||||||
|
@ -72,12 +71,6 @@ public class CommonController extends AbstractErrorController {
|
||||||
*/
|
*/
|
||||||
@GetMapping
|
@GetMapping
|
||||||
public String handleError(HttpServletRequest request, HttpServletResponse response, Model model) {
|
public String handleError(HttpServletRequest request, HttpServletResponse response, Model model) {
|
||||||
log.error("Request URL: [{}], URI: [{}], Request Method: [{}], IP: [{}]",
|
|
||||||
request.getRequestURL(),
|
|
||||||
request.getRequestURI(),
|
|
||||||
request.getMethod(),
|
|
||||||
ServletUtil.getClientIP(request));
|
|
||||||
|
|
||||||
handleCustomException(request);
|
handleCustomException(request);
|
||||||
|
|
||||||
ErrorAttributeOptions options = getErrorAttributeOptions(request);
|
ErrorAttributeOptions options = getErrorAttributeOptions(request);
|
||||||
|
@ -168,9 +161,12 @@ public class CommonController extends AbstractErrorController {
|
||||||
Throwable throwable = (Throwable) throwableObject;
|
Throwable throwable = (Throwable) throwableObject;
|
||||||
|
|
||||||
if (throwable instanceof NestedServletException) {
|
if (throwable instanceof NestedServletException) {
|
||||||
log.error("Captured an exception", throwable);
|
log.error("Captured an exception: [{}]", throwable.getMessage());
|
||||||
Throwable rootCause = ((NestedServletException) throwable).getRootCause();
|
Throwable rootCause = ((NestedServletException) throwable).getRootCause();
|
||||||
if (rootCause instanceof AbstractHaloException) {
|
if (rootCause instanceof AbstractHaloException) {
|
||||||
|
if (!(rootCause instanceof NotFoundException)) {
|
||||||
|
log.error("Caused by", rootCause);
|
||||||
|
}
|
||||||
AbstractHaloException haloException = (AbstractHaloException) rootCause;
|
AbstractHaloException haloException = (AbstractHaloException) rootCause;
|
||||||
request.setAttribute("javax.servlet.error.status_code", haloException.getStatus().value());
|
request.setAttribute("javax.servlet.error.status_code", haloException.getStatus().value());
|
||||||
request.setAttribute("javax.servlet.error.exception", rootCause);
|
request.setAttribute("javax.servlet.error.exception", rootCause);
|
||||||
|
|
|
@ -140,11 +140,10 @@ public class ControllerExceptionHandler {
|
||||||
BaseResponse<T> baseResponse = new BaseResponse<>();
|
BaseResponse<T> baseResponse = new BaseResponse<>();
|
||||||
baseResponse.setMessage(t.getMessage());
|
baseResponse.setMessage(t.getMessage());
|
||||||
|
|
||||||
|
log.error("Captured an exception:", t);
|
||||||
|
|
||||||
if (log.isDebugEnabled()) {
|
if (log.isDebugEnabled()) {
|
||||||
log.error("Captured an exception:", t);
|
|
||||||
baseResponse.setDevMessage(ExceptionUtils.getStackTrace(t));
|
baseResponse.setDevMessage(ExceptionUtils.getStackTrace(t));
|
||||||
} else {
|
|
||||||
log.error("Captured an exception: [{}]", t.getMessage());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return baseResponse;
|
return baseResponse;
|
||||||
|
|
|
@ -7,11 +7,13 @@ import org.aspectj.lang.ProceedingJoinPoint;
|
||||||
import org.aspectj.lang.annotation.Around;
|
import org.aspectj.lang.annotation.Around;
|
||||||
import org.aspectj.lang.annotation.Aspect;
|
import org.aspectj.lang.annotation.Aspect;
|
||||||
import org.aspectj.lang.annotation.Pointcut;
|
import org.aspectj.lang.annotation.Pointcut;
|
||||||
|
import org.aspectj.lang.reflect.MethodSignature;
|
||||||
import org.springframework.core.io.Resource;
|
import org.springframework.core.io.Resource;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.lang.NonNull;
|
import org.springframework.lang.NonNull;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
import org.springframework.util.StopWatch;
|
||||||
import org.springframework.web.context.request.RequestContextHolder;
|
import org.springframework.web.context.request.RequestContextHolder;
|
||||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
@ -19,6 +21,7 @@ import run.halo.app.utils.JsonUtils;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -29,12 +32,19 @@ import java.util.Objects;
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class ControllerLogAop {
|
public class ControllerLogAop {
|
||||||
|
|
||||||
@Pointcut("execution(* *..*.*.controller..*.*(..))")
|
@Pointcut("@within(org.springframework.stereotype.Controller)")
|
||||||
public void controller() {
|
public void controller() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Around("controller()")
|
@Around("controller()")
|
||||||
public Object controller(ProceedingJoinPoint joinPoint) throws Throwable {
|
public Object controller(ProceedingJoinPoint joinPoint) throws Throwable {
|
||||||
|
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
|
||||||
|
final Method method = signature.getMethod();
|
||||||
|
if (method == null || !log.isDebugEnabled()) {
|
||||||
|
// should never happen
|
||||||
|
return joinPoint.proceed();
|
||||||
|
}
|
||||||
|
|
||||||
String className = joinPoint.getTarget().getClass().getSimpleName();
|
String className = joinPoint.getTarget().getClass().getSimpleName();
|
||||||
String methodName = joinPoint.getSignature().getName();
|
String methodName = joinPoint.getSignature().getName();
|
||||||
Object[] args = joinPoint.getArgs();
|
Object[] args = joinPoint.getArgs();
|
||||||
|
@ -43,14 +53,25 @@ public class ControllerLogAop {
|
||||||
ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
|
ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
|
||||||
HttpServletRequest request = Objects.requireNonNull(requestAttributes).getRequest();
|
HttpServletRequest request = Objects.requireNonNull(requestAttributes).getRequest();
|
||||||
|
|
||||||
|
final StopWatch watch = new StopWatch(request.getRequestURI());
|
||||||
|
|
||||||
|
watch.start("PrintRequest");
|
||||||
printRequestLog(request, className, methodName, args);
|
printRequestLog(request, className, methodName, args);
|
||||||
long start = System.currentTimeMillis();
|
watch.stop();
|
||||||
Object returnObj = joinPoint.proceed();
|
|
||||||
printResponseLog(request, className, methodName, returnObj, System.currentTimeMillis() - start);
|
watch.start(className + "#" + methodName);
|
||||||
|
final Object returnObj = joinPoint.proceed();
|
||||||
|
watch.stop();
|
||||||
|
|
||||||
|
watch.start("PrintResponse");
|
||||||
|
printResponseLog(request, className, methodName, returnObj);
|
||||||
|
watch.stop();
|
||||||
|
if (log.isDebugEnabled()) {
|
||||||
|
log.debug("Usage:\n{}", watch.prettyPrint());
|
||||||
|
}
|
||||||
return returnObj;
|
return returnObj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void printRequestLog(HttpServletRequest request, String clazzName, String methodName, Object[] args) throws JsonProcessingException {
|
private void printRequestLog(HttpServletRequest request, String clazzName, String methodName, Object[] args) throws JsonProcessingException {
|
||||||
log.debug("Request URL: [{}], URI: [{}], Request Method: [{}], IP: [{}]",
|
log.debug("Request URL: [{}], URI: [{}], Request Method: [{}], IP: [{}]",
|
||||||
request.getRequestURL(),
|
request.getRequestURL(),
|
||||||
|
@ -80,16 +101,16 @@ public class ControllerLogAop {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void printResponseLog(HttpServletRequest request, String className, String methodName, Object returnObj, long usage) throws JsonProcessingException {
|
private void printResponseLog(HttpServletRequest request, String className, String methodName, Object returnObj)
|
||||||
|
throws JsonProcessingException {
|
||||||
if (log.isDebugEnabled()) {
|
if (log.isDebugEnabled()) {
|
||||||
String returnData = "";
|
String returnData = "";
|
||||||
|
|
||||||
if (returnObj != null) {
|
if (returnObj != null) {
|
||||||
if (returnObj instanceof ResponseEntity) {
|
if (returnObj instanceof ResponseEntity) {
|
||||||
ResponseEntity responseEntity = (ResponseEntity) returnObj;
|
ResponseEntity<?> responseEntity = (ResponseEntity<?>) returnObj;
|
||||||
if (responseEntity.getBody() instanceof Resource) {
|
if (responseEntity.getBody() instanceof Resource) {
|
||||||
returnData = "[ BINARY DATA ]";
|
returnData = "[ BINARY DATA ]";
|
||||||
} else {
|
} else if (responseEntity.getBody() != null) {
|
||||||
returnData = toString(responseEntity.getBody());
|
returnData = toString(responseEntity.getBody());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -97,7 +118,7 @@ public class ControllerLogAop {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
log.debug("{}.{} Response: [{}], usage: [{}]ms", className, methodName, returnData, usage);
|
log.debug("{}.{} Response: [{}]", className, methodName, returnData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,7 +126,7 @@ public class ControllerLogAop {
|
||||||
private String toString(@NonNull Object obj) throws JsonProcessingException {
|
private String toString(@NonNull Object obj) throws JsonProcessingException {
|
||||||
Assert.notNull(obj, "Return object must not be null");
|
Assert.notNull(obj, "Return object must not be null");
|
||||||
|
|
||||||
String toString = "";
|
String toString;
|
||||||
if (obj.getClass().isAssignableFrom(byte[].class) && obj instanceof Resource) {
|
if (obj.getClass().isAssignableFrom(byte[].class) && obj instanceof Resource) {
|
||||||
toString = "[ BINARY DATA ]";
|
toString = "[ BINARY DATA ]";
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -20,24 +20,30 @@ import java.io.IOException;
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Component
|
@Component
|
||||||
@Order(Ordered.HIGHEST_PRECEDENCE + 9)
|
@Order(Ordered.HIGHEST_PRECEDENCE)
|
||||||
public class LogFilter extends OncePerRequestFilter {
|
public class LogFilter extends OncePerRequestFilter {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
|
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
|
||||||
|
|
||||||
String remoteAddr = ServletUtil.getClientIP(request);
|
final String remoteAddr = ServletUtil.getClientIP(request);
|
||||||
|
|
||||||
log.debug("");
|
log.debug("Starting url: [{}], method: [{}], ip: [{}]",
|
||||||
log.debug("Starting url: [{}], method: [{}], ip: [{}]", request.getRequestURL(), request.getMethod(), remoteAddr);
|
request.getRequestURL(),
|
||||||
|
request.getMethod(),
|
||||||
|
remoteAddr);
|
||||||
|
|
||||||
// Set start time
|
// Set start time
|
||||||
long startTime = System.currentTimeMillis();
|
final long startTime = System.currentTimeMillis();
|
||||||
|
|
||||||
// Do filter
|
// Do filter
|
||||||
filterChain.doFilter(request, response);
|
filterChain.doFilter(request, response);
|
||||||
|
|
||||||
log.debug("Ending url: [{}], method: [{}], ip: [{}], status: [{}], usage: [{}] ms", request.getRequestURL(), request.getMethod(), remoteAddr, response.getStatus(), System.currentTimeMillis() - startTime);
|
log.debug("Ending url: [{}], method: [{}], ip: [{}], status: [{}], usage: [{}] ms",
|
||||||
log.debug("");
|
request.getRequestURL(),
|
||||||
|
request.getMethod(),
|
||||||
|
remoteAddr,
|
||||||
|
response.getStatus(),
|
||||||
|
System.currentTimeMillis() - startTime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,6 @@ import run.halo.app.service.OptionService;
|
||||||
import run.halo.app.utils.FilenameUtils;
|
import run.halo.app.utils.FilenameUtils;
|
||||||
import run.halo.app.utils.ImageUtils;
|
import run.halo.app.utils.ImageUtils;
|
||||||
|
|
||||||
import javax.imageio.ImageReader;
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
import static run.halo.app.model.support.HaloConst.URL_SEPARATOR;
|
import static run.halo.app.model.support.HaloConst.URL_SEPARATOR;
|
||||||
|
@ -72,10 +71,10 @@ public class AliOssFileHandler implements FileHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
String basename = FilenameUtils.getBasename(Objects.requireNonNull(file.getOriginalFilename()));
|
final String basename = FilenameUtils.getBasename(Objects.requireNonNull(file.getOriginalFilename()));
|
||||||
String extension = FilenameUtils.getExtension(file.getOriginalFilename());
|
final String extension = FilenameUtils.getExtension(file.getOriginalFilename());
|
||||||
String timestamp = String.valueOf(System.currentTimeMillis());
|
final String timestamp = String.valueOf(System.currentTimeMillis());
|
||||||
StringBuilder upFilePath = new StringBuilder();
|
final StringBuilder upFilePath = new StringBuilder();
|
||||||
|
|
||||||
if (StringUtils.isNotEmpty(source)) {
|
if (StringUtils.isNotEmpty(source)) {
|
||||||
upFilePath.append(source)
|
upFilePath.append(source)
|
||||||
|
@ -93,13 +92,16 @@ public class AliOssFileHandler implements FileHandler {
|
||||||
log.info(basePath.toString());
|
log.info(basePath.toString());
|
||||||
|
|
||||||
// Upload
|
// Upload
|
||||||
PutObjectResult putObjectResult = ossClient.putObject(bucketName, upFilePath.toString(), file.getInputStream());
|
final PutObjectResult putObjectResult = ossClient.putObject(bucketName,
|
||||||
|
upFilePath.toString(),
|
||||||
|
file.getInputStream());
|
||||||
|
|
||||||
if (putObjectResult == null) {
|
if (putObjectResult == null) {
|
||||||
throw new FileOperationException("上传附件 " + file.getOriginalFilename() + " 到阿里云失败 ");
|
throw new FileOperationException("上传附件 " + file.getOriginalFilename() + " 到阿里云失败 ");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Response result
|
// Response result
|
||||||
UploadResult uploadResult = new UploadResult();
|
final UploadResult uploadResult = new UploadResult();
|
||||||
uploadResult.setFilename(basename);
|
uploadResult.setFilename(basename);
|
||||||
uploadResult.setFilePath(StringUtils.isBlank(styleRule) ? filePath : filePath + styleRule);
|
uploadResult.setFilePath(StringUtils.isBlank(styleRule) ? filePath : filePath + styleRule);
|
||||||
uploadResult.setKey(upFilePath.toString());
|
uploadResult.setKey(upFilePath.toString());
|
||||||
|
@ -107,18 +109,13 @@ public class AliOssFileHandler implements FileHandler {
|
||||||
uploadResult.setSuffix(extension);
|
uploadResult.setSuffix(extension);
|
||||||
uploadResult.setSize(file.getSize());
|
uploadResult.setSize(file.getSize());
|
||||||
|
|
||||||
// Handle thumbnail
|
handleImageMetadata(file, uploadResult, () -> {
|
||||||
if (FileHandler.isImageType(uploadResult.getMediaType())) {
|
|
||||||
ImageReader image = ImageUtils.getImageReaderFromFile(file.getInputStream(), extension);
|
|
||||||
assert image != null;
|
|
||||||
uploadResult.setWidth(image.getWidth(0));
|
|
||||||
uploadResult.setHeight(image.getHeight(0));
|
|
||||||
if (ImageUtils.EXTENSION_ICO.equals(extension)) {
|
if (ImageUtils.EXTENSION_ICO.equals(extension)) {
|
||||||
uploadResult.setThumbPath(filePath);
|
return filePath;
|
||||||
} else {
|
} else {
|
||||||
uploadResult.setThumbPath(StringUtils.isBlank(thumbnailStyleRule) ? filePath : filePath + thumbnailStyleRule);
|
return StringUtils.isBlank(thumbnailStyleRule) ? filePath : filePath + thumbnailStyleRule;
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
log.info("Uploaded file: [{}] successfully", file.getOriginalFilename());
|
log.info("Uploaded file: [{}] successfully", file.getOriginalFilename());
|
||||||
return uploadResult;
|
return uploadResult;
|
||||||
|
|
|
@ -19,7 +19,6 @@ import run.halo.app.service.OptionService;
|
||||||
import run.halo.app.utils.FilenameUtils;
|
import run.halo.app.utils.FilenameUtils;
|
||||||
import run.halo.app.utils.ImageUtils;
|
import run.halo.app.utils.ImageUtils;
|
||||||
|
|
||||||
import javax.imageio.ImageReader;
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -86,17 +85,13 @@ public class BaiduBosFileHandler implements FileHandler {
|
||||||
uploadResult.setSize(file.getSize());
|
uploadResult.setSize(file.getSize());
|
||||||
|
|
||||||
// Handle thumbnail
|
// Handle thumbnail
|
||||||
if (FileHandler.isImageType(uploadResult.getMediaType())) {
|
handleImageMetadata(file, uploadResult, () -> {
|
||||||
ImageReader image = ImageUtils.getImageReaderFromFile(file.getInputStream(), extension);
|
|
||||||
assert image != null;
|
|
||||||
uploadResult.setWidth(image.getWidth(0));
|
|
||||||
uploadResult.setHeight(image.getHeight(0));
|
|
||||||
if (ImageUtils.EXTENSION_ICO.equals(extension)) {
|
if (ImageUtils.EXTENSION_ICO.equals(extension)) {
|
||||||
uploadResult.setThumbPath(filePath);
|
return filePath;
|
||||||
} else {
|
} else {
|
||||||
uploadResult.setThumbPath(StringUtils.isBlank(thumbnailStyleRule) ? filePath : filePath + thumbnailStyleRule);
|
return StringUtils.isBlank(thumbnailStyleRule) ? filePath : filePath + thumbnailStyleRule;
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
return uploadResult;
|
return uploadResult;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package run.halo.app.handler.file;
|
package run.halo.app.handler.file;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.lang.NonNull;
|
import org.springframework.lang.NonNull;
|
||||||
import org.springframework.lang.Nullable;
|
import org.springframework.lang.Nullable;
|
||||||
|
@ -9,6 +10,12 @@ import org.springframework.web.multipart.MultipartFile;
|
||||||
import run.halo.app.exception.FileOperationException;
|
import run.halo.app.exception.FileOperationException;
|
||||||
import run.halo.app.model.enums.AttachmentType;
|
import run.halo.app.model.enums.AttachmentType;
|
||||||
import run.halo.app.model.support.UploadResult;
|
import run.halo.app.model.support.UploadResult;
|
||||||
|
import run.halo.app.utils.ImageUtils;
|
||||||
|
|
||||||
|
import javax.imageio.ImageReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import static run.halo.app.model.support.HaloConst.FILE_SEPARATOR;
|
import static run.halo.app.model.support.HaloConst.FILE_SEPARATOR;
|
||||||
|
|
||||||
|
@ -22,39 +29,6 @@ public interface FileHandler {
|
||||||
|
|
||||||
MediaType IMAGE_TYPE = MediaType.valueOf("image/*");
|
MediaType IMAGE_TYPE = MediaType.valueOf("image/*");
|
||||||
|
|
||||||
/**
|
|
||||||
* Check whether media type provided is an image type.
|
|
||||||
*
|
|
||||||
* @param mediaType media type provided
|
|
||||||
* @return true if it is an image type
|
|
||||||
*/
|
|
||||||
static boolean isImageType(@Nullable String mediaType) {
|
|
||||||
return mediaType != null && IMAGE_TYPE.includes(MediaType.valueOf(mediaType));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check whether media type provided is an image type.
|
|
||||||
*
|
|
||||||
* @param mediaType media type provided
|
|
||||||
* @return true if it is an image type
|
|
||||||
*/
|
|
||||||
static boolean isImageType(@Nullable MediaType mediaType) {
|
|
||||||
return mediaType != null && IMAGE_TYPE.includes(mediaType);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Normalize directory full name, ensure the end path separator.
|
|
||||||
*
|
|
||||||
* @param dir directory full name must not be blank
|
|
||||||
* @return normalized directory full name with end path separator
|
|
||||||
*/
|
|
||||||
@NonNull
|
|
||||||
static String normalizeDirectory(@NonNull String dir) {
|
|
||||||
Assert.hasText(dir, "Directory full name must not be blank");
|
|
||||||
|
|
||||||
return StringUtils.appendIfMissing(dir, FILE_SEPARATOR);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Uploads file.
|
* Uploads file.
|
||||||
*
|
*
|
||||||
|
@ -65,6 +39,44 @@ public interface FileHandler {
|
||||||
@NonNull
|
@NonNull
|
||||||
UploadResult upload(@NonNull MultipartFile file);
|
UploadResult upload(@NonNull MultipartFile file);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the current file is an image.
|
||||||
|
*
|
||||||
|
* @param file multipart file must not be null
|
||||||
|
* @return true if the current file is an image, false otherwise
|
||||||
|
*/
|
||||||
|
default boolean isImageType(@NonNull MultipartFile file) {
|
||||||
|
String mediaType = file.getContentType();
|
||||||
|
return mediaType != null && IMAGE_TYPE.includes(MediaType.valueOf(mediaType));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param uploadResult updated result must not be null
|
||||||
|
* @param file multipart file must not be null
|
||||||
|
* @param thumbnailSupplier thumbnail supplier
|
||||||
|
*/
|
||||||
|
default void handleImageMetadata(@NonNull MultipartFile file,
|
||||||
|
@NonNull UploadResult uploadResult,
|
||||||
|
@Nullable Supplier<String> thumbnailSupplier) {
|
||||||
|
if (isImageType(file)) {
|
||||||
|
// Handle image
|
||||||
|
try (InputStream is = file.getInputStream()) {
|
||||||
|
ImageReader image = ImageUtils.getImageReaderFromFile(is, uploadResult.getSuffix());
|
||||||
|
uploadResult.setWidth(image.getWidth(0));
|
||||||
|
uploadResult.setHeight(image.getHeight(0));
|
||||||
|
if (thumbnailSupplier != null) {
|
||||||
|
uploadResult.setThumbPath(thumbnailSupplier.get());
|
||||||
|
}
|
||||||
|
} catch (IOException | OutOfMemoryError e) {
|
||||||
|
// ignore IOException and OOM
|
||||||
|
LoggerFactory.getLogger(getClass()).warn("Failed to fetch image meta data", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (StringUtils.isBlank(uploadResult.getThumbPath())) {
|
||||||
|
uploadResult.setThumbPath(uploadResult.getFilePath());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes file.
|
* Deletes file.
|
||||||
*
|
*
|
||||||
|
@ -79,4 +91,18 @@ public interface FileHandler {
|
||||||
* @return attachment type
|
* @return attachment type
|
||||||
*/
|
*/
|
||||||
AttachmentType getAttachmentType();
|
AttachmentType getAttachmentType();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Normalize directory full name, ensure the end path separator.
|
||||||
|
*
|
||||||
|
* @param dir directory full name must not be blank
|
||||||
|
* @return normalized directory full name with end path separator
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
static String normalizeDirectory(@NonNull String dir) {
|
||||||
|
Assert.hasText(dir, "Directory full name must not be blank");
|
||||||
|
|
||||||
|
return StringUtils.appendIfMissing(dir, FILE_SEPARATOR);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -51,7 +51,6 @@ public class FileHandlers {
|
||||||
return getSupportedType(attachmentType).upload(file);
|
return getSupportedType(attachmentType).upload(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes attachment.
|
* Deletes attachment.
|
||||||
*
|
*
|
||||||
|
|
|
@ -17,7 +17,6 @@ import run.halo.app.service.OptionService;
|
||||||
import run.halo.app.utils.FilenameUtils;
|
import run.halo.app.utils.FilenameUtils;
|
||||||
import run.halo.app.utils.ImageUtils;
|
import run.halo.app.utils.ImageUtils;
|
||||||
|
|
||||||
import javax.imageio.ImageReader;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
|
@ -105,18 +104,13 @@ public class HuaweiObsFileHandler implements FileHandler {
|
||||||
uploadResult.setSuffix(extension);
|
uploadResult.setSuffix(extension);
|
||||||
uploadResult.setSize(file.getSize());
|
uploadResult.setSize(file.getSize());
|
||||||
|
|
||||||
// Handle thumbnail
|
handleImageMetadata(file, uploadResult, () -> {
|
||||||
if (FileHandler.isImageType(uploadResult.getMediaType())) {
|
|
||||||
ImageReader image = ImageUtils.getImageReaderFromFile(file.getInputStream(), extension);
|
|
||||||
assert image != null;
|
|
||||||
uploadResult.setWidth(image.getWidth(0));
|
|
||||||
uploadResult.setHeight(image.getHeight(0));
|
|
||||||
if (ImageUtils.EXTENSION_ICO.equals(extension)) {
|
if (ImageUtils.EXTENSION_ICO.equals(extension)) {
|
||||||
uploadResult.setThumbPath(filePath);
|
return filePath;
|
||||||
} else {
|
} else {
|
||||||
uploadResult.setThumbPath(StringUtils.isBlank(thumbnailStyleRule) ? filePath : filePath + thumbnailStyleRule);
|
return StringUtils.isBlank(thumbnailStyleRule) ? filePath : filePath + thumbnailStyleRule;
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
log.info("Uploaded file: [{}] successfully", file.getOriginalFilename());
|
log.info("Uploaded file: [{}] successfully", file.getOriginalFilename());
|
||||||
return uploadResult;
|
return uploadResult;
|
||||||
|
|
|
@ -16,7 +16,6 @@ import run.halo.app.utils.HaloUtils;
|
||||||
import run.halo.app.utils.ImageUtils;
|
import run.halo.app.utils.ImageUtils;
|
||||||
|
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
|
@ -55,9 +54,12 @@ public class LocalFileHandler implements FileHandler {
|
||||||
* Thumbnail height.
|
* Thumbnail height.
|
||||||
*/
|
*/
|
||||||
private final static int THUMB_HEIGHT = 256;
|
private final static int THUMB_HEIGHT = 256;
|
||||||
|
|
||||||
private final OptionService optionService;
|
private final OptionService optionService;
|
||||||
|
|
||||||
private final String workDir;
|
private final String workDir;
|
||||||
ReentrantLock lock = new ReentrantLock();
|
|
||||||
|
private final ReentrantLock lock = new ReentrantLock();
|
||||||
|
|
||||||
public LocalFileHandler(OptionService optionService,
|
public LocalFileHandler(OptionService optionService,
|
||||||
HaloProperties haloProperties) {
|
HaloProperties haloProperties) {
|
||||||
|
@ -139,38 +141,24 @@ public class LocalFileHandler implements FileHandler {
|
||||||
uploadResult.setSize(file.getSize());
|
uploadResult.setSize(file.getSize());
|
||||||
|
|
||||||
// TODO refactor this: if image is svg ext. extension
|
// TODO refactor this: if image is svg ext. extension
|
||||||
boolean isSvg = "svg".equals(extension);
|
handleImageMetadata(file, uploadResult, () -> {
|
||||||
|
// Upload a thumbnail
|
||||||
// Check file type
|
final String thumbnailBasename = basename + THUMBNAIL_SUFFIX;
|
||||||
if (FileHandler.isImageType(uploadResult.getMediaType()) && !isSvg) {
|
final String thumbnailSubFilePath = subDir + thumbnailBasename + '.' + extension;
|
||||||
lock.lock();
|
final Path thumbnailPath = Paths.get(workDir + thumbnailSubFilePath);
|
||||||
try (InputStream uploadFileInputStream = new FileInputStream(uploadPath.toFile())) {
|
try (InputStream is = file.getInputStream()) {
|
||||||
// Upload a thumbnail
|
|
||||||
String thumbnailBasename = basename + THUMBNAIL_SUFFIX;
|
|
||||||
String thumbnailSubFilePath = subDir + thumbnailBasename + '.' + extension;
|
|
||||||
Path thumbnailPath = Paths.get(workDir + thumbnailSubFilePath);
|
|
||||||
|
|
||||||
// Read as image
|
|
||||||
BufferedImage originalImage = ImageUtils.getImageFromFile(uploadFileInputStream, extension);
|
|
||||||
// Set width and height
|
|
||||||
uploadResult.setWidth(originalImage.getWidth());
|
|
||||||
uploadResult.setHeight(originalImage.getHeight());
|
|
||||||
|
|
||||||
// Generate thumbnail
|
// Generate thumbnail
|
||||||
|
BufferedImage originalImage = ImageUtils.getImageFromFile(is, extension);
|
||||||
boolean result = generateThumbnail(originalImage, thumbnailPath, extension);
|
boolean result = generateThumbnail(originalImage, thumbnailPath, extension);
|
||||||
if (result) {
|
if (result) {
|
||||||
// Set thumb path
|
// Set thumb path
|
||||||
uploadResult.setThumbPath(thumbnailSubFilePath);
|
return thumbnailSubFilePath;
|
||||||
} else {
|
|
||||||
// If generate error
|
|
||||||
uploadResult.setThumbPath(subFilePath);
|
|
||||||
}
|
}
|
||||||
} finally {
|
} catch (IOException e) {
|
||||||
lock.unlock();
|
log.warn("Failed to open image file.", e);
|
||||||
}
|
}
|
||||||
} else {
|
return subFilePath;
|
||||||
uploadResult.setThumbPath(subFilePath);
|
});
|
||||||
}
|
|
||||||
|
|
||||||
log.info("Uploaded file: [{}] to directory: [{}] successfully", file.getOriginalFilename(), uploadPath.toString());
|
log.info("Uploaded file: [{}] to directory: [{}] successfully", file.getOriginalFilename(), uploadPath.toString());
|
||||||
return uploadResult;
|
return uploadResult;
|
||||||
|
@ -222,7 +210,6 @@ public class LocalFileHandler implements FileHandler {
|
||||||
Assert.notNull(originalImage, "Image must not be null");
|
Assert.notNull(originalImage, "Image must not be null");
|
||||||
Assert.notNull(thumbPath, "Thumb path must not be null");
|
Assert.notNull(thumbPath, "Thumb path must not be null");
|
||||||
|
|
||||||
|
|
||||||
boolean result = false;
|
boolean result = false;
|
||||||
// Create the thumbnail
|
// Create the thumbnail
|
||||||
try {
|
try {
|
||||||
|
@ -230,15 +217,14 @@ public class LocalFileHandler implements FileHandler {
|
||||||
// Convert to thumbnail and copy the thumbnail
|
// Convert to thumbnail and copy the thumbnail
|
||||||
log.debug("Trying to generate thumbnail: [{}]", thumbPath.toString());
|
log.debug("Trying to generate thumbnail: [{}]", thumbPath.toString());
|
||||||
Thumbnails.of(originalImage).size(THUMB_WIDTH, THUMB_HEIGHT).keepAspectRatio(true).toFile(thumbPath.toFile());
|
Thumbnails.of(originalImage).size(THUMB_WIDTH, THUMB_HEIGHT).keepAspectRatio(true).toFile(thumbPath.toFile());
|
||||||
log.debug("Generated thumbnail image, and wrote the thumbnail to [{}]", thumbPath.toString());
|
log.info("Generated thumbnail image, and wrote the thumbnail to [{}]", thumbPath.toString());
|
||||||
result = true;
|
result = true;
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
|
// Ignore the error
|
||||||
log.warn("Failed to generate thumbnail: " + thumbPath, t);
|
log.warn("Failed to generate thumbnail: " + thumbPath, t);
|
||||||
} finally {
|
} finally {
|
||||||
// Disposes of this graphics context and releases any system resources that it is using.
|
// Disposes of this graphics context and releases any system resources that it is using.
|
||||||
if (originalImage != null) {
|
originalImage.getGraphics().dispose();
|
||||||
originalImage.getGraphics().dispose();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,9 +17,7 @@ import run.halo.app.model.support.HaloConst;
|
||||||
import run.halo.app.model.support.UploadResult;
|
import run.halo.app.model.support.UploadResult;
|
||||||
import run.halo.app.service.OptionService;
|
import run.halo.app.service.OptionService;
|
||||||
import run.halo.app.utils.FilenameUtils;
|
import run.halo.app.utils.FilenameUtils;
|
||||||
import run.halo.app.utils.ImageUtils;
|
|
||||||
|
|
||||||
import javax.imageio.ImageReader;
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
|
|
||||||
|
@ -82,13 +80,7 @@ public class MinioFileHandler implements FileHandler {
|
||||||
uploadResult.setSize(file.getSize());
|
uploadResult.setSize(file.getSize());
|
||||||
|
|
||||||
// Handle thumbnail
|
// Handle thumbnail
|
||||||
if (FileHandler.isImageType(uploadResult.getMediaType())) {
|
handleImageMetadata(file, uploadResult, () -> filePath);
|
||||||
ImageReader image = ImageUtils.getImageReaderFromFile(file.getInputStream(), extension);
|
|
||||||
assert image != null;
|
|
||||||
uploadResult.setWidth(image.getWidth(0));
|
|
||||||
uploadResult.setHeight(image.getHeight(0));
|
|
||||||
uploadResult.setThumbPath(filePath);
|
|
||||||
}
|
|
||||||
|
|
||||||
return uploadResult;
|
return uploadResult;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|
|
@ -31,7 +31,6 @@ import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
import static run.halo.app.handler.file.FileHandler.isImageType;
|
|
||||||
import static run.halo.app.model.support.HaloConst.*;
|
import static run.halo.app.model.support.HaloConst.*;
|
||||||
import static run.halo.app.utils.HaloUtils.ensureSuffix;
|
import static run.halo.app.utils.HaloUtils.ensureSuffix;
|
||||||
|
|
||||||
|
@ -129,7 +128,7 @@ public class QiniuOssFileHandler implements FileHandler {
|
||||||
result.setMediaType(MediaType.valueOf(Objects.requireNonNull(file.getContentType())));
|
result.setMediaType(MediaType.valueOf(Objects.requireNonNull(file.getContentType())));
|
||||||
result.setSize(file.getSize());
|
result.setSize(file.getSize());
|
||||||
|
|
||||||
if (isImageType(result.getMediaType())) {
|
if (isImageType(file)) {
|
||||||
if (ImageUtils.EXTENSION_ICO.equals(extension)) {
|
if (ImageUtils.EXTENSION_ICO.equals(extension)) {
|
||||||
result.setThumbPath(filePath);
|
result.setThumbPath(filePath);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -76,7 +76,7 @@ public class SmmsFileHandler implements FileHandler {
|
||||||
throw new ServiceException("请先设置 SM.MS 的 Secret Token");
|
throw new ServiceException("请先设置 SM.MS 的 Secret Token");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!FileHandler.isImageType(file.getContentType())) {
|
if (!isImageType(file)) {
|
||||||
log.error("Invalid extension: [{}]", file.getContentType());
|
log.error("Invalid extension: [{}]", file.getContentType());
|
||||||
throw new FileOperationException("不支持的文件类型,仅支持 \"jpeg, jpg, png, gif, bmp\" 格式的图片");
|
throw new FileOperationException("不支持的文件类型,仅支持 \"jpeg, jpg, png, gif, bmp\" 格式的图片");
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,6 @@ import run.halo.app.service.OptionService;
|
||||||
import run.halo.app.utils.FilenameUtils;
|
import run.halo.app.utils.FilenameUtils;
|
||||||
import run.halo.app.utils.ImageUtils;
|
import run.halo.app.utils.ImageUtils;
|
||||||
|
|
||||||
import javax.imageio.ImageReader;
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
import static run.halo.app.model.support.HaloConst.URL_SEPARATOR;
|
import static run.halo.app.model.support.HaloConst.URL_SEPARATOR;
|
||||||
|
@ -119,18 +118,14 @@ public class TencentCosFileHandler implements FileHandler {
|
||||||
uploadResult.setSize(file.getSize());
|
uploadResult.setSize(file.getSize());
|
||||||
|
|
||||||
// Handle thumbnail
|
// Handle thumbnail
|
||||||
if (FileHandler.isImageType(uploadResult.getMediaType())) {
|
handleImageMetadata(file, uploadResult, () -> {
|
||||||
ImageReader image = ImageUtils.getImageReaderFromFile(file.getInputStream(), extension);
|
|
||||||
assert image != null;
|
|
||||||
uploadResult.setWidth(image.getWidth(0));
|
|
||||||
uploadResult.setHeight(image.getHeight(0));
|
|
||||||
if (ImageUtils.EXTENSION_ICO.equals(extension)) {
|
if (ImageUtils.EXTENSION_ICO.equals(extension)) {
|
||||||
uploadResult.setThumbPath(filePath);
|
uploadResult.setThumbPath(filePath);
|
||||||
|
return filePath;
|
||||||
} else {
|
} else {
|
||||||
uploadResult.setThumbPath(StringUtils.isBlank(thumbnailStyleRule) ? filePath : filePath + thumbnailStyleRule);
|
return StringUtils.isBlank(thumbnailStyleRule) ? filePath : filePath + thumbnailStyleRule;
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
return uploadResult;
|
return uploadResult;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new FileOperationException("附件 " + file.getOriginalFilename() + " 上传失败(腾讯云)", e);
|
throw new FileOperationException("附件 " + file.getOriginalFilename() + " 上传失败(腾讯云)", e);
|
||||||
|
|
|
@ -18,7 +18,6 @@ import run.halo.app.service.OptionService;
|
||||||
import run.halo.app.utils.FilenameUtils;
|
import run.halo.app.utils.FilenameUtils;
|
||||||
import run.halo.app.utils.ImageUtils;
|
import run.halo.app.utils.ImageUtils;
|
||||||
|
|
||||||
import javax.imageio.ImageReader;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -90,18 +89,14 @@ public class UpOssFileHandler implements FileHandler {
|
||||||
uploadResult.setSize(file.getSize());
|
uploadResult.setSize(file.getSize());
|
||||||
|
|
||||||
// Handle thumbnail
|
// Handle thumbnail
|
||||||
if (FileHandler.isImageType(uploadResult.getMediaType())) {
|
handleImageMetadata(file, uploadResult, () -> {
|
||||||
ImageReader image = ImageUtils.getImageReaderFromFile(file.getInputStream(), extension);
|
|
||||||
assert image != null;
|
|
||||||
uploadResult.setWidth(image.getWidth(0));
|
|
||||||
uploadResult.setHeight(image.getHeight(0));
|
|
||||||
if (ImageUtils.EXTENSION_ICO.equals(extension)) {
|
if (ImageUtils.EXTENSION_ICO.equals(extension)) {
|
||||||
uploadResult.setThumbPath(filePath);
|
uploadResult.setThumbPath(filePath);
|
||||||
|
return filePath;
|
||||||
} else {
|
} else {
|
||||||
uploadResult.setThumbPath(StringUtils.isBlank(thumbnailStyleRule) ? filePath : filePath + thumbnailStyleRule);
|
return StringUtils.isBlank(thumbnailStyleRule) ? filePath : filePath + thumbnailStyleRule;
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
return uploadResult;
|
return uploadResult;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new FileOperationException("上传附件 " + file.getOriginalFilename() + " 到又拍云失败", e);
|
throw new FileOperationException("上传附件 " + file.getOriginalFilename() + " 到又拍云失败", e);
|
||||||
|
|
|
@ -2,6 +2,7 @@ package run.halo.app.utils;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import net.sf.image4j.codec.ico.ICODecoder;
|
import net.sf.image4j.codec.ico.ICODecoder;
|
||||||
|
import org.springframework.lang.NonNull;
|
||||||
import run.halo.app.exception.ImageFormatException;
|
import run.halo.app.exception.ImageFormatException;
|
||||||
|
|
||||||
import javax.imageio.ImageIO;
|
import javax.imageio.ImageIO;
|
||||||
|
@ -35,7 +36,8 @@ public class ImageUtils {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ImageReader getImageReaderFromFile(InputStream is, String formatName) {
|
@NonNull
|
||||||
|
public static ImageReader getImageReaderFromFile(InputStream is, String formatName) throws IOException {
|
||||||
try {
|
try {
|
||||||
Iterator<ImageReader> readerIterator = ImageIO.getImageReadersByFormatName(formatName);
|
Iterator<ImageReader> readerIterator = ImageIO.getImageReadersByFormatName(formatName);
|
||||||
ImageReader reader = readerIterator.next();
|
ImageReader reader = readerIterator.next();
|
||||||
|
@ -43,9 +45,8 @@ public class ImageUtils {
|
||||||
ImageIO.getImageReadersByFormatName(formatName);
|
ImageIO.getImageReadersByFormatName(formatName);
|
||||||
reader.setInput(stream, true);
|
reader.setInput(stream, true);
|
||||||
return reader;
|
return reader;
|
||||||
} catch (IOException e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
throw new IOException("Failed to read image reader.", e);
|
||||||
}
|
}
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,6 +47,7 @@ management:
|
||||||
logging:
|
logging:
|
||||||
level:
|
level:
|
||||||
run.halo.app: INFO
|
run.halo.app: INFO
|
||||||
|
org.eclipse.jetty.server.HttpChannel: ERROR
|
||||||
file:
|
file:
|
||||||
path: ${user.home}/.halo/logs
|
path: ${user.home}/.halo/logs
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue