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"
|
||||
image4jVersion = "0.7zensight1"
|
||||
flywayVersion = "6.5.0"
|
||||
h2Version = "1.4.196"
|
||||
h2Version = "1.4.197"
|
||||
levelDbVersion = "0.12"
|
||||
annotationsVersion = "3.0.1u2"
|
||||
zxingVersion = "3.4.0"
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
distributionBase=GRADLE_USER_HOME
|
||||
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
|
||||
zipStorePath=wrapper/dists
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package run.halo.app.controller.core;
|
||||
|
||||
import cn.hutool.extra.servlet.ServletUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.boot.autoconfigure.web.ErrorProperties;
|
||||
import org.springframework.boot.autoconfigure.web.ServerProperties;
|
||||
|
@ -72,12 +71,6 @@ public class CommonController extends AbstractErrorController {
|
|||
*/
|
||||
@GetMapping
|
||||
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);
|
||||
|
||||
ErrorAttributeOptions options = getErrorAttributeOptions(request);
|
||||
|
@ -168,9 +161,12 @@ public class CommonController extends AbstractErrorController {
|
|||
Throwable throwable = (Throwable) throwableObject;
|
||||
|
||||
if (throwable instanceof NestedServletException) {
|
||||
log.error("Captured an exception", throwable);
|
||||
log.error("Captured an exception: [{}]", throwable.getMessage());
|
||||
Throwable rootCause = ((NestedServletException) throwable).getRootCause();
|
||||
if (rootCause instanceof AbstractHaloException) {
|
||||
if (!(rootCause instanceof NotFoundException)) {
|
||||
log.error("Caused by", rootCause);
|
||||
}
|
||||
AbstractHaloException haloException = (AbstractHaloException) rootCause;
|
||||
request.setAttribute("javax.servlet.error.status_code", haloException.getStatus().value());
|
||||
request.setAttribute("javax.servlet.error.exception", rootCause);
|
||||
|
|
|
@ -140,11 +140,10 @@ public class ControllerExceptionHandler {
|
|||
BaseResponse<T> baseResponse = new BaseResponse<>();
|
||||
baseResponse.setMessage(t.getMessage());
|
||||
|
||||
log.error("Captured an exception:", t);
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.error("Captured an exception:", t);
|
||||
baseResponse.setDevMessage(ExceptionUtils.getStackTrace(t));
|
||||
} else {
|
||||
log.error("Captured an exception: [{}]", t.getMessage());
|
||||
}
|
||||
|
||||
return baseResponse;
|
||||
|
|
|
@ -7,11 +7,13 @@ import org.aspectj.lang.ProceedingJoinPoint;
|
|||
import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.aspectj.lang.annotation.Pointcut;
|
||||
import org.aspectj.lang.reflect.MethodSignature;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StopWatch;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
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.HttpServletResponse;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
|
@ -29,12 +32,19 @@ import java.util.Objects;
|
|||
@Slf4j
|
||||
public class ControllerLogAop {
|
||||
|
||||
@Pointcut("execution(* *..*.*.controller..*.*(..))")
|
||||
@Pointcut("@within(org.springframework.stereotype.Controller)")
|
||||
public void controller() {
|
||||
}
|
||||
|
||||
@Around("controller()")
|
||||
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 methodName = joinPoint.getSignature().getName();
|
||||
Object[] args = joinPoint.getArgs();
|
||||
|
@ -43,14 +53,25 @@ public class ControllerLogAop {
|
|||
ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
|
||||
HttpServletRequest request = Objects.requireNonNull(requestAttributes).getRequest();
|
||||
|
||||
final StopWatch watch = new StopWatch(request.getRequestURI());
|
||||
|
||||
watch.start("PrintRequest");
|
||||
printRequestLog(request, className, methodName, args);
|
||||
long start = System.currentTimeMillis();
|
||||
Object returnObj = joinPoint.proceed();
|
||||
printResponseLog(request, className, methodName, returnObj, System.currentTimeMillis() - start);
|
||||
watch.stop();
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
private void printRequestLog(HttpServletRequest request, String clazzName, String methodName, Object[] args) throws JsonProcessingException {
|
||||
log.debug("Request URL: [{}], URI: [{}], Request Method: [{}], IP: [{}]",
|
||||
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()) {
|
||||
String returnData = "";
|
||||
|
||||
if (returnObj != null) {
|
||||
if (returnObj instanceof ResponseEntity) {
|
||||
ResponseEntity responseEntity = (ResponseEntity) returnObj;
|
||||
ResponseEntity<?> responseEntity = (ResponseEntity<?>) returnObj;
|
||||
if (responseEntity.getBody() instanceof Resource) {
|
||||
returnData = "[ BINARY DATA ]";
|
||||
} else {
|
||||
} else if (responseEntity.getBody() != null) {
|
||||
returnData = toString(responseEntity.getBody());
|
||||
}
|
||||
} 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 {
|
||||
Assert.notNull(obj, "Return object must not be null");
|
||||
|
||||
String toString = "";
|
||||
String toString;
|
||||
if (obj.getClass().isAssignableFrom(byte[].class) && obj instanceof Resource) {
|
||||
toString = "[ BINARY DATA ]";
|
||||
} else {
|
||||
|
|
|
@ -20,24 +20,30 @@ import java.io.IOException;
|
|||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@Order(Ordered.HIGHEST_PRECEDENCE + 9)
|
||||
@Order(Ordered.HIGHEST_PRECEDENCE)
|
||||
public class LogFilter extends OncePerRequestFilter {
|
||||
|
||||
@Override
|
||||
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: [{}]", request.getRequestURL(), request.getMethod(), remoteAddr);
|
||||
log.debug("Starting url: [{}], method: [{}], ip: [{}]",
|
||||
request.getRequestURL(),
|
||||
request.getMethod(),
|
||||
remoteAddr);
|
||||
|
||||
// Set start time
|
||||
long startTime = System.currentTimeMillis();
|
||||
final long startTime = System.currentTimeMillis();
|
||||
|
||||
// Do filter
|
||||
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("");
|
||||
log.debug("Ending url: [{}], method: [{}], ip: [{}], status: [{}], usage: [{}] ms",
|
||||
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.ImageUtils;
|
||||
|
||||
import javax.imageio.ImageReader;
|
||||
import java.util.Objects;
|
||||
|
||||
import static run.halo.app.model.support.HaloConst.URL_SEPARATOR;
|
||||
|
@ -72,10 +71,10 @@ public class AliOssFileHandler implements FileHandler {
|
|||
}
|
||||
|
||||
try {
|
||||
String basename = FilenameUtils.getBasename(Objects.requireNonNull(file.getOriginalFilename()));
|
||||
String extension = FilenameUtils.getExtension(file.getOriginalFilename());
|
||||
String timestamp = String.valueOf(System.currentTimeMillis());
|
||||
StringBuilder upFilePath = new StringBuilder();
|
||||
final String basename = FilenameUtils.getBasename(Objects.requireNonNull(file.getOriginalFilename()));
|
||||
final String extension = FilenameUtils.getExtension(file.getOriginalFilename());
|
||||
final String timestamp = String.valueOf(System.currentTimeMillis());
|
||||
final StringBuilder upFilePath = new StringBuilder();
|
||||
|
||||
if (StringUtils.isNotEmpty(source)) {
|
||||
upFilePath.append(source)
|
||||
|
@ -93,13 +92,16 @@ public class AliOssFileHandler implements FileHandler {
|
|||
log.info(basePath.toString());
|
||||
|
||||
// Upload
|
||||
PutObjectResult putObjectResult = ossClient.putObject(bucketName, upFilePath.toString(), file.getInputStream());
|
||||
final PutObjectResult putObjectResult = ossClient.putObject(bucketName,
|
||||
upFilePath.toString(),
|
||||
file.getInputStream());
|
||||
|
||||
if (putObjectResult == null) {
|
||||
throw new FileOperationException("上传附件 " + file.getOriginalFilename() + " 到阿里云失败 ");
|
||||
}
|
||||
|
||||
// Response result
|
||||
UploadResult uploadResult = new UploadResult();
|
||||
final UploadResult uploadResult = new UploadResult();
|
||||
uploadResult.setFilename(basename);
|
||||
uploadResult.setFilePath(StringUtils.isBlank(styleRule) ? filePath : filePath + styleRule);
|
||||
uploadResult.setKey(upFilePath.toString());
|
||||
|
@ -107,18 +109,13 @@ public class AliOssFileHandler implements FileHandler {
|
|||
uploadResult.setSuffix(extension);
|
||||
uploadResult.setSize(file.getSize());
|
||||
|
||||
// Handle thumbnail
|
||||
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));
|
||||
handleImageMetadata(file, uploadResult, () -> {
|
||||
if (ImageUtils.EXTENSION_ICO.equals(extension)) {
|
||||
uploadResult.setThumbPath(filePath);
|
||||
return filePath;
|
||||
} else {
|
||||
uploadResult.setThumbPath(StringUtils.isBlank(thumbnailStyleRule) ? filePath : filePath + thumbnailStyleRule);
|
||||
return StringUtils.isBlank(thumbnailStyleRule) ? filePath : filePath + thumbnailStyleRule;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
log.info("Uploaded file: [{}] successfully", file.getOriginalFilename());
|
||||
return uploadResult;
|
||||
|
|
|
@ -19,7 +19,6 @@ import run.halo.app.service.OptionService;
|
|||
import run.halo.app.utils.FilenameUtils;
|
||||
import run.halo.app.utils.ImageUtils;
|
||||
|
||||
import javax.imageio.ImageReader;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
|
@ -86,17 +85,13 @@ public class BaiduBosFileHandler implements FileHandler {
|
|||
uploadResult.setSize(file.getSize());
|
||||
|
||||
// Handle thumbnail
|
||||
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));
|
||||
handleImageMetadata(file, uploadResult, () -> {
|
||||
if (ImageUtils.EXTENSION_ICO.equals(extension)) {
|
||||
uploadResult.setThumbPath(filePath);
|
||||
return filePath;
|
||||
} else {
|
||||
uploadResult.setThumbPath(StringUtils.isBlank(thumbnailStyleRule) ? filePath : filePath + thumbnailStyleRule);
|
||||
return StringUtils.isBlank(thumbnailStyleRule) ? filePath : filePath + thumbnailStyleRule;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return uploadResult;
|
||||
} catch (Exception e) {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package run.halo.app.handler.file;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.lang.NonNull;
|
||||
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.model.enums.AttachmentType;
|
||||
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;
|
||||
|
||||
|
@ -22,39 +29,6 @@ public interface FileHandler {
|
|||
|
||||
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.
|
||||
*
|
||||
|
@ -65,6 +39,44 @@ public interface FileHandler {
|
|||
@NonNull
|
||||
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.
|
||||
*
|
||||
|
@ -79,4 +91,18 @@ public interface FileHandler {
|
|||
* @return attachment type
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Deletes attachment.
|
||||
*
|
||||
|
|
|
@ -17,7 +17,6 @@ import run.halo.app.service.OptionService;
|
|||
import run.halo.app.utils.FilenameUtils;
|
||||
import run.halo.app.utils.ImageUtils;
|
||||
|
||||
import javax.imageio.ImageReader;
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
|
||||
|
@ -105,18 +104,13 @@ public class HuaweiObsFileHandler implements FileHandler {
|
|||
uploadResult.setSuffix(extension);
|
||||
uploadResult.setSize(file.getSize());
|
||||
|
||||
// Handle thumbnail
|
||||
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));
|
||||
handleImageMetadata(file, uploadResult, () -> {
|
||||
if (ImageUtils.EXTENSION_ICO.equals(extension)) {
|
||||
uploadResult.setThumbPath(filePath);
|
||||
return filePath;
|
||||
} else {
|
||||
uploadResult.setThumbPath(StringUtils.isBlank(thumbnailStyleRule) ? filePath : filePath + thumbnailStyleRule);
|
||||
return StringUtils.isBlank(thumbnailStyleRule) ? filePath : filePath + thumbnailStyleRule;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
log.info("Uploaded file: [{}] successfully", file.getOriginalFilename());
|
||||
return uploadResult;
|
||||
|
|
|
@ -16,7 +16,6 @@ import run.halo.app.utils.HaloUtils;
|
|||
import run.halo.app.utils.ImageUtils;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Files;
|
||||
|
@ -55,9 +54,12 @@ public class LocalFileHandler implements FileHandler {
|
|||
* Thumbnail height.
|
||||
*/
|
||||
private final static int THUMB_HEIGHT = 256;
|
||||
|
||||
private final OptionService optionService;
|
||||
|
||||
private final String workDir;
|
||||
ReentrantLock lock = new ReentrantLock();
|
||||
|
||||
private final ReentrantLock lock = new ReentrantLock();
|
||||
|
||||
public LocalFileHandler(OptionService optionService,
|
||||
HaloProperties haloProperties) {
|
||||
|
@ -139,38 +141,24 @@ public class LocalFileHandler implements FileHandler {
|
|||
uploadResult.setSize(file.getSize());
|
||||
|
||||
// TODO refactor this: if image is svg ext. extension
|
||||
boolean isSvg = "svg".equals(extension);
|
||||
|
||||
// Check file type
|
||||
if (FileHandler.isImageType(uploadResult.getMediaType()) && !isSvg) {
|
||||
lock.lock();
|
||||
try (InputStream uploadFileInputStream = new FileInputStream(uploadPath.toFile())) {
|
||||
// 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());
|
||||
|
||||
handleImageMetadata(file, uploadResult, () -> {
|
||||
// Upload a thumbnail
|
||||
final String thumbnailBasename = basename + THUMBNAIL_SUFFIX;
|
||||
final String thumbnailSubFilePath = subDir + thumbnailBasename + '.' + extension;
|
||||
final Path thumbnailPath = Paths.get(workDir + thumbnailSubFilePath);
|
||||
try (InputStream is = file.getInputStream()) {
|
||||
// Generate thumbnail
|
||||
BufferedImage originalImage = ImageUtils.getImageFromFile(is, extension);
|
||||
boolean result = generateThumbnail(originalImage, thumbnailPath, extension);
|
||||
if (result) {
|
||||
// Set thumb path
|
||||
uploadResult.setThumbPath(thumbnailSubFilePath);
|
||||
} else {
|
||||
// If generate error
|
||||
uploadResult.setThumbPath(subFilePath);
|
||||
return thumbnailSubFilePath;
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
} catch (IOException e) {
|
||||
log.warn("Failed to open image file.", e);
|
||||
}
|
||||
} else {
|
||||
uploadResult.setThumbPath(subFilePath);
|
||||
}
|
||||
return subFilePath;
|
||||
});
|
||||
|
||||
log.info("Uploaded file: [{}] to directory: [{}] successfully", file.getOriginalFilename(), uploadPath.toString());
|
||||
return uploadResult;
|
||||
|
@ -222,7 +210,6 @@ public class LocalFileHandler implements FileHandler {
|
|||
Assert.notNull(originalImage, "Image must not be null");
|
||||
Assert.notNull(thumbPath, "Thumb path must not be null");
|
||||
|
||||
|
||||
boolean result = false;
|
||||
// Create the thumbnail
|
||||
try {
|
||||
|
@ -230,15 +217,14 @@ public class LocalFileHandler implements FileHandler {
|
|||
// Convert to thumbnail and copy the thumbnail
|
||||
log.debug("Trying to generate thumbnail: [{}]", thumbPath.toString());
|
||||
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;
|
||||
} catch (Throwable t) {
|
||||
// Ignore the error
|
||||
log.warn("Failed to generate thumbnail: " + thumbPath, t);
|
||||
} finally {
|
||||
// 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;
|
||||
}
|
||||
|
|
|
@ -17,9 +17,7 @@ import run.halo.app.model.support.HaloConst;
|
|||
import run.halo.app.model.support.UploadResult;
|
||||
import run.halo.app.service.OptionService;
|
||||
import run.halo.app.utils.FilenameUtils;
|
||||
import run.halo.app.utils.ImageUtils;
|
||||
|
||||
import javax.imageio.ImageReader;
|
||||
import java.util.Objects;
|
||||
|
||||
|
||||
|
@ -82,13 +80,7 @@ public class MinioFileHandler implements FileHandler {
|
|||
uploadResult.setSize(file.getSize());
|
||||
|
||||
// Handle thumbnail
|
||||
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));
|
||||
uploadResult.setThumbPath(filePath);
|
||||
}
|
||||
handleImageMetadata(file, uploadResult, () -> filePath);
|
||||
|
||||
return uploadResult;
|
||||
} catch (Exception e) {
|
||||
|
|
|
@ -31,7 +31,6 @@ import java.nio.file.Path;
|
|||
import java.nio.file.Paths;
|
||||
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.utils.HaloUtils.ensureSuffix;
|
||||
|
||||
|
@ -129,7 +128,7 @@ public class QiniuOssFileHandler implements FileHandler {
|
|||
result.setMediaType(MediaType.valueOf(Objects.requireNonNull(file.getContentType())));
|
||||
result.setSize(file.getSize());
|
||||
|
||||
if (isImageType(result.getMediaType())) {
|
||||
if (isImageType(file)) {
|
||||
if (ImageUtils.EXTENSION_ICO.equals(extension)) {
|
||||
result.setThumbPath(filePath);
|
||||
} else {
|
||||
|
|
|
@ -76,7 +76,7 @@ public class SmmsFileHandler implements FileHandler {
|
|||
throw new ServiceException("请先设置 SM.MS 的 Secret Token");
|
||||
}
|
||||
|
||||
if (!FileHandler.isImageType(file.getContentType())) {
|
||||
if (!isImageType(file)) {
|
||||
log.error("Invalid extension: [{}]", file.getContentType());
|
||||
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.ImageUtils;
|
||||
|
||||
import javax.imageio.ImageReader;
|
||||
import java.util.Objects;
|
||||
|
||||
import static run.halo.app.model.support.HaloConst.URL_SEPARATOR;
|
||||
|
@ -119,18 +118,14 @@ public class TencentCosFileHandler implements FileHandler {
|
|||
uploadResult.setSize(file.getSize());
|
||||
|
||||
// Handle thumbnail
|
||||
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));
|
||||
handleImageMetadata(file, uploadResult, () -> {
|
||||
if (ImageUtils.EXTENSION_ICO.equals(extension)) {
|
||||
uploadResult.setThumbPath(filePath);
|
||||
return filePath;
|
||||
} else {
|
||||
uploadResult.setThumbPath(StringUtils.isBlank(thumbnailStyleRule) ? filePath : filePath + thumbnailStyleRule);
|
||||
return StringUtils.isBlank(thumbnailStyleRule) ? filePath : filePath + thumbnailStyleRule;
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
return uploadResult;
|
||||
} catch (Exception 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.ImageUtils;
|
||||
|
||||
import javax.imageio.ImageReader;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
@ -90,18 +89,14 @@ public class UpOssFileHandler implements FileHandler {
|
|||
uploadResult.setSize(file.getSize());
|
||||
|
||||
// Handle thumbnail
|
||||
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));
|
||||
handleImageMetadata(file, uploadResult, () -> {
|
||||
if (ImageUtils.EXTENSION_ICO.equals(extension)) {
|
||||
uploadResult.setThumbPath(filePath);
|
||||
return filePath;
|
||||
} else {
|
||||
uploadResult.setThumbPath(StringUtils.isBlank(thumbnailStyleRule) ? filePath : filePath + thumbnailStyleRule);
|
||||
return StringUtils.isBlank(thumbnailStyleRule) ? filePath : filePath + thumbnailStyleRule;
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
return uploadResult;
|
||||
} catch (Exception e) {
|
||||
throw new FileOperationException("上传附件 " + file.getOriginalFilename() + " 到又拍云失败", e);
|
||||
|
|
|
@ -2,6 +2,7 @@ package run.halo.app.utils;
|
|||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.sf.image4j.codec.ico.ICODecoder;
|
||||
import org.springframework.lang.NonNull;
|
||||
import run.halo.app.exception.ImageFormatException;
|
||||
|
||||
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 {
|
||||
Iterator<ImageReader> readerIterator = ImageIO.getImageReadersByFormatName(formatName);
|
||||
ImageReader reader = readerIterator.next();
|
||||
|
@ -43,9 +45,8 @@ public class ImageUtils {
|
|||
ImageIO.getImageReadersByFormatName(formatName);
|
||||
reader.setInput(stream, true);
|
||||
return reader;
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} catch (Exception e) {
|
||||
throw new IOException("Failed to read image reader.", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,6 +47,7 @@ management:
|
|||
logging:
|
||||
level:
|
||||
run.halo.app: INFO
|
||||
org.eclipse.jetty.server.HttpChannel: ERROR
|
||||
file:
|
||||
path: ${user.home}/.halo/logs
|
||||
|
||||
|
|
Loading…
Reference in New Issue