mirror of https://github.com/halo-dev/halo
Optimize FileHandler's logic (#639)
* optimize FileHandler's logic * fix code style * fix: maybe happen OOM when file upload, see #529 * refactor: HashMap -> ConcurrentHashMap * remove unused classpull/662/head
parent
153f8ebbef
commit
1d020ff550
|
@ -0,0 +1,15 @@
|
||||||
|
package run.halo.app.exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* repeat type exception
|
||||||
|
* @author bestsort
|
||||||
|
* @date 3/13/20 5:03 PM
|
||||||
|
*/
|
||||||
|
public class RepeatTypeException extends ServiceException {
|
||||||
|
public RepeatTypeException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
public RepeatTypeException(String message, Throwable cause) {
|
||||||
|
super(message, cause);
|
||||||
|
}
|
||||||
|
}
|
|
@ -148,7 +148,8 @@ public class AliOssFileHandler implements FileHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean supportType(String type) {
|
public AttachmentType getAttachmentType() {
|
||||||
return AttachmentType.ALIOSS.name().equalsIgnoreCase(type);
|
return AttachmentType.ALIOSS;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -132,7 +132,7 @@ public class BaiduBosFileHandler implements FileHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean supportType(String type) {
|
public AttachmentType getAttachmentType() {
|
||||||
return AttachmentType.BAIDUBOS.name().equalsIgnoreCase(type);
|
return AttachmentType.BAIDUBOS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ import org.springframework.lang.Nullable;
|
||||||
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.exception.FileOperationException;
|
import run.halo.app.exception.FileOperationException;
|
||||||
|
import run.halo.app.model.enums.AttachmentType;
|
||||||
import run.halo.app.model.support.UploadResult;
|
import run.halo.app.model.support.UploadResult;
|
||||||
|
|
||||||
import static run.halo.app.model.support.HaloConst.FILE_SEPARATOR;
|
import static run.halo.app.model.support.HaloConst.FILE_SEPARATOR;
|
||||||
|
@ -73,10 +74,8 @@ public interface FileHandler {
|
||||||
void delete(@NonNull String key);
|
void delete(@NonNull String key);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the given type is supported.
|
* Get attachment type is supported.
|
||||||
*
|
* @return attachment type
|
||||||
* @param type attachment type
|
|
||||||
* @return true if supported; false otherwise
|
|
||||||
*/
|
*/
|
||||||
boolean supportType(@Nullable String type);
|
AttachmentType getAttachmentType();
|
||||||
}
|
}
|
|
@ -9,12 +9,13 @@ import org.springframework.util.Assert;
|
||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
import run.halo.app.exception.FileOperationException;
|
import run.halo.app.exception.FileOperationException;
|
||||||
|
import run.halo.app.exception.RepeatTypeException;
|
||||||
import run.halo.app.model.entity.Attachment;
|
import run.halo.app.model.entity.Attachment;
|
||||||
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 java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.LinkedList;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* File handler manager.
|
* File handler manager.
|
||||||
|
@ -29,7 +30,7 @@ public class FileHandlers {
|
||||||
/**
|
/**
|
||||||
* File handler container.
|
* File handler container.
|
||||||
*/
|
*/
|
||||||
private final Collection<FileHandler> fileHandlers = new LinkedList<>();
|
private final ConcurrentHashMap<AttachmentType, FileHandler> fileHandlers = new ConcurrentHashMap<>(16);
|
||||||
|
|
||||||
public FileHandlers(ApplicationContext applicationContext) {
|
public FileHandlers(ApplicationContext applicationContext) {
|
||||||
// Add all file handler
|
// Add all file handler
|
||||||
|
@ -47,31 +48,9 @@ public class FileHandlers {
|
||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
public UploadResult upload(@NonNull MultipartFile file, @NonNull AttachmentType attachmentType) {
|
public UploadResult upload(@NonNull MultipartFile file, @NonNull AttachmentType attachmentType) {
|
||||||
Assert.notNull(attachmentType, "Attachment type must not be null");
|
return getSupportedType(attachmentType).upload(file);
|
||||||
|
|
||||||
return upload(file, attachmentType.name());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Uploads files.
|
|
||||||
*
|
|
||||||
* @param file multipart file must not be null
|
|
||||||
* @param type store type
|
|
||||||
* @return upload result
|
|
||||||
* @throws FileOperationException throws when fail to delete attachment or no available file handler to upload it
|
|
||||||
*/
|
|
||||||
@NonNull
|
|
||||||
public UploadResult upload(@NonNull MultipartFile file, @Nullable String type) {
|
|
||||||
Assert.notNull(file, "Multipart file must not be null");
|
|
||||||
|
|
||||||
for (FileHandler fileHandler : fileHandlers) {
|
|
||||||
if (fileHandler.supportType(type)) {
|
|
||||||
return fileHandler.upload(file);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new FileOperationException("No available file handlers to upload the file").setErrorData(type);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes attachment.
|
* Deletes attachment.
|
||||||
|
@ -81,26 +60,8 @@ public class FileHandlers {
|
||||||
*/
|
*/
|
||||||
public void delete(@NonNull Attachment attachment) {
|
public void delete(@NonNull Attachment attachment) {
|
||||||
Assert.notNull(attachment, "Attachment must not be null");
|
Assert.notNull(attachment, "Attachment must not be null");
|
||||||
|
getSupportedType(attachment.getType())
|
||||||
delete(attachment.getType().name(), attachment.getFileKey());
|
.delete(attachment.getFileKey());
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Deletes attachment.
|
|
||||||
*
|
|
||||||
* @param key file key
|
|
||||||
* @throws FileOperationException throws when fail to delete attachment or no available file handler to delete it
|
|
||||||
*/
|
|
||||||
public void delete(@Nullable String type, @NonNull String key) {
|
|
||||||
for (FileHandler fileHandler : fileHandlers) {
|
|
||||||
if (fileHandler.supportType(type)) {
|
|
||||||
// Delete the file
|
|
||||||
fileHandler.delete(key);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new FileOperationException("No available file handlers to delete the file").setErrorData(type);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -112,8 +73,21 @@ public class FileHandlers {
|
||||||
@NonNull
|
@NonNull
|
||||||
public FileHandlers addFileHandlers(@Nullable Collection<FileHandler> fileHandlers) {
|
public FileHandlers addFileHandlers(@Nullable Collection<FileHandler> fileHandlers) {
|
||||||
if (!CollectionUtils.isEmpty(fileHandlers)) {
|
if (!CollectionUtils.isEmpty(fileHandlers)) {
|
||||||
this.fileHandlers.addAll(fileHandlers);
|
for (FileHandler handler : fileHandlers) {
|
||||||
|
if (this.fileHandlers.containsKey(handler.getAttachmentType())) {
|
||||||
|
throw new RepeatTypeException("Same attachment type implements must be unique");
|
||||||
|
}
|
||||||
|
this.fileHandlers.put(handler.getAttachmentType(), handler);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private FileHandler getSupportedType(AttachmentType type) {
|
||||||
|
FileHandler handler = fileHandlers.getOrDefault(type, fileHandlers.get(AttachmentType.LOCAL));
|
||||||
|
if (handler == null) {
|
||||||
|
throw new FileOperationException("No available file handlers to operate the file").setErrorData(type);
|
||||||
|
}
|
||||||
|
return handler;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -214,8 +214,8 @@ public class LocalFileHandler implements FileHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean supportType(String type) {
|
public AttachmentType getAttachmentType() {
|
||||||
return AttachmentType.LOCAL.name().equalsIgnoreCase(type);
|
return AttachmentType.LOCAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean generateThumbnail(BufferedImage originalImage, Path thumbPath, String extension) {
|
private boolean generateThumbnail(BufferedImage originalImage, Path thumbPath, String extension) {
|
||||||
|
@ -234,6 +234,9 @@ public class LocalFileHandler implements FileHandler {
|
||||||
result = true;
|
result = true;
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
log.warn("Failed to generate thumbnail: " + thumbPath, t);
|
log.warn("Failed to generate thumbnail: " + thumbPath, t);
|
||||||
|
} finally {
|
||||||
|
// Disposes of this graphics context and releases any system resources that it is using.
|
||||||
|
originalImage.getGraphics().dispose();
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -177,7 +177,7 @@ public class QiniuOssFileHandler implements FileHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean supportType(String type) {
|
public AttachmentType getAttachmentType() {
|
||||||
return AttachmentType.QINIUOSS.name().equalsIgnoreCase(type);
|
return AttachmentType.QINIUOSS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -165,8 +165,8 @@ public class SmmsFileHandler implements FileHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean supportType(String type) {
|
public AttachmentType getAttachmentType() {
|
||||||
return AttachmentType.SMMS.name().equalsIgnoreCase(type);
|
return AttachmentType.SMMS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -163,7 +163,7 @@ public class TencentCosFileHandler implements FileHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean supportType(String type) {
|
public AttachmentType getAttachmentType() {
|
||||||
return AttachmentType.TENCENTCOS.name().equalsIgnoreCase(type);
|
return AttachmentType.TENCENTCOS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -128,7 +128,7 @@ public class UpOssFileHandler implements FileHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean supportType(String type) {
|
public AttachmentType getAttachmentType() {
|
||||||
return AttachmentType.UPOSS.name().equalsIgnoreCase(type);
|
return AttachmentType.UPOSS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -934,7 +934,6 @@ public class ThemeServiceImpl implements ThemeService {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue