Complete local file deletion service

pull/137/head
johnniang 2019-03-27 19:19:54 +08:00
parent 69b77ac245
commit b6f1a29951
10 changed files with 111 additions and 46 deletions

View File

@ -0,0 +1,17 @@
package cc.ryanc.halo.exception;
/**
* File operation exception.
*
* @author johnniang
* @date 3/27/19
*/
public class FileOperationException extends ServiceException {
public FileOperationException(String message) {
super(message);
}
public FileOperationException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@ -1,17 +0,0 @@
package cc.ryanc.halo.exception;
/**
* File upload exception.
*
* @author johnniang
* @date 3/27/19
*/
public class FileUploadException extends ServiceException {
public FileUploadException(String message) {
super(message);
}
public FileUploadException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@ -1,6 +1,6 @@
package cc.ryanc.halo.filehandler;
import cc.ryanc.halo.exception.FileUploadException;
import cc.ryanc.halo.exception.FileOperationException;
import cc.ryanc.halo.model.enums.AttachmentType;
import cc.ryanc.halo.model.support.UploadResult;
import org.apache.commons.lang3.StringUtils;
@ -27,7 +27,7 @@ public interface FileHandler {
*
* @param file multipart file must not be null
* @return upload result
* @throws FileUploadException throws when fail to upload the file
* @throws FileOperationException throws when fail to upload the file
*/
@NonNull
UploadResult upload(@NonNull MultipartFile file);
@ -37,7 +37,7 @@ public interface FileHandler {
*
* @param key file key must not be null
*/
boolean delete(@NonNull String key);
void delete(@NonNull String key);
/**
* Checks if the given type is supported.
@ -45,7 +45,7 @@ public interface FileHandler {
* @param type attachment type
* @return true if supported; false or else
*/
boolean supportType(AttachmentType type);
boolean supportType(@Nullable AttachmentType type);
/**

View File

@ -1,6 +1,6 @@
package cc.ryanc.halo.filehandler;
import cc.ryanc.halo.exception.FileUploadException;
import cc.ryanc.halo.exception.FileOperationException;
import cc.ryanc.halo.model.enums.AttachmentType;
import cc.ryanc.halo.model.support.UploadResult;
import lombok.extern.slf4j.Slf4j;
@ -42,18 +42,19 @@ public class FileHandlers {
}
log.error("There is no available file handle for attachment type: [{}]", attachmentType);
throw new FileUploadException("No available file handler to filehandler the file").setErrorData(attachmentType);
throw new FileOperationException("No available file handler to filehandler the file").setErrorData(attachmentType);
}
public boolean delete(String key, AttachmentType attachmentType) {
public void delete(String key, AttachmentType attachmentType) {
for (FileHandler fileHandler : fileHandlers) {
if (fileHandler.supportType(attachmentType)) {
return fileHandler.delete(key);
fileHandler.delete(key);
return;
}
}
log.error("There is no available file handle for attachment type: [{}]", attachmentType);
throw new FileUploadException("No available file handler to delete the file").setErrorData(attachmentType);
throw new FileOperationException("No available file handler to delete the file").setErrorData(attachmentType);
}
/**

View File

@ -1,6 +1,7 @@
package cc.ryanc.halo.filehandler;
import cc.ryanc.halo.config.properties.HaloProperties;
import cc.ryanc.halo.exception.FileOperationException;
import cc.ryanc.halo.exception.ServiceException;
import cc.ryanc.halo.model.enums.AttachmentType;
import cc.ryanc.halo.model.support.UploadResult;
@ -36,7 +37,9 @@ public class LocalFileHandler implements FileHandler {
/**
* Upload sub directory.
*/
private final static String UPLOAD_SUB_DIR = "upload";
private final static String UPLOAD_SUB_DIR = "upload/";
private final static String THUMBNAIL_SUFFIX = "-thumbnail";
/**
* Thumbnail width.
@ -59,6 +62,8 @@ public class LocalFileHandler implements FileHandler {
// Get work dir
workDir = FileHandler.normalizeDirectory(haloProperties.getWorkDir());
// Check work directory
checkWorkDir();
}
/**
@ -89,7 +94,7 @@ public class LocalFileHandler implements FileHandler {
int month = current.get(Calendar.MONTH) + 1;
// Build directory
String subDir = UPLOAD_SUB_DIR + File.separator + year + File.separator + month + File.separator;
String subDir = UPLOAD_SUB_DIR + year + File.separator + month + File.separator;
// Get basename
String basename = FilenameUtils.getBasename(file.getOriginalFilename()) + '-' + HaloUtils.randomUUIDWithoutDash();
@ -103,9 +108,9 @@ public class LocalFileHandler implements FileHandler {
String subFilePath = subDir + basename + '.' + extension;
// Get upload path
Path uploadPath = Paths.get(workDir + subFilePath);
Path uploadPath = Paths.get(workDir, subFilePath);
log.info("Uploading to directory: [{}]", uploadPath.getFileName());
log.info("Uploading to directory: [{}]", uploadPath.toString());
try {
// TODO Synchronize here
@ -128,7 +133,7 @@ public class LocalFileHandler implements FileHandler {
// Check file type
if (FileHandler.isImageType(uploadResult.getMediaType())) {
// Upload a thumbnail
String thumbnailBasename = basename + '-' + "thumbnail";
String thumbnailBasename = basename + THUMBNAIL_SUFFIX;
String thumbnailSubFilePath = subDir + thumbnailBasename + '.' + extension;
Path thumbnailPath = Paths.get(workDir + thumbnailSubFilePath);
@ -151,14 +156,44 @@ public class LocalFileHandler implements FileHandler {
return uploadResult;
} catch (IOException e) {
log.error("Failed to upload file to local: " + uploadPath.getFileName(), e);
throw new ServiceException("Failed to upload file to local").setErrorData(uploadPath.getFileName());
log.error("Failed to upload file to local: " + uploadPath, e);
throw new ServiceException("Failed to upload file to local").setErrorData(uploadPath);
}
}
@Override
public boolean delete(String key) {
return false;
public void delete(String key) {
Assert.hasText(key, "File key must not be blank");
// Get path
Path path = Paths.get(workDir, key);
// Delete the file key
try {
Files.delete(path);
} catch (IOException e) {
throw new FileOperationException("Failed to delete " + key + " file", e);
}
// Delete thumb if necessary
String basename = FilenameUtils.getBasename(key);
String extension = FilenameUtils.getExtension(key);
// Get thumbnail name
String thumbnailName = basename + THUMBNAIL_SUFFIX + '.' + extension;
// Get thumbnail path
Path thumbnailPath = Paths.get(path.getParent().toString(), thumbnailName);
// Delete thumbnail file
try {
boolean deleteResult = Files.deleteIfExists(thumbnailPath);
if (!deleteResult) {
log.warn("Thumbnail: [{}] way not exist", thumbnailPath.toString());
}
} catch (IOException e) {
throw new FileOperationException("Failed to delete " + thumbnailName + " thumbnail", e);
}
}
@Override
@ -182,4 +217,5 @@ public class LocalFileHandler implements FileHandler {
// Convert to thumbnail and copy the thumbnail
Thumbnails.of(imagePath.toFile()).size(THUMB_WIDTH, THUMB_HEIGHT).keepAspectRatio(true).toFile(thumbPath.toFile());
}
}

View File

@ -1,6 +1,6 @@
package cc.ryanc.halo.filehandler;
import cc.ryanc.halo.exception.FileUploadException;
import cc.ryanc.halo.exception.FileOperationException;
import cc.ryanc.halo.model.enums.AttachmentType;
import cc.ryanc.halo.model.enums.QnYunProperties;
import cc.ryanc.halo.model.support.QiNiuPutSet;
@ -118,13 +118,13 @@ public class QnYunFileHandler implements FileHandler {
log.error("QnYun error response: [{}]", ((QiniuException) e).response);
}
throw new FileUploadException("Failed to upload file " + file.getOriginalFilename() + " to QnYun", e);
throw new FileOperationException("Failed to upload file " + file.getOriginalFilename() + " to QnYun", e);
}
}
@Override
public boolean delete(String key) {
return false;
public void delete(String key) {
// TODO Handle file deletion
}
@Override

View File

@ -1,6 +1,6 @@
package cc.ryanc.halo.filehandler;
import cc.ryanc.halo.exception.FileUploadException;
import cc.ryanc.halo.exception.FileOperationException;
import cc.ryanc.halo.exception.PropertyFormatException;
import cc.ryanc.halo.model.enums.AttachmentType;
import cc.ryanc.halo.model.enums.UpYunProperties;
@ -72,7 +72,7 @@ public class UpYunFileHandler implements FileHandler {
// Write file
boolean uploadSuccess = upYun.writeFile(upFilePath, file.getInputStream(), true, null);
if (!uploadSuccess) {
throw new FileUploadException("Failed to upload file " + file.getOriginalFilename() + " to UpYun " + upFilePath);
throw new FileOperationException("Failed to upload file " + file.getOriginalFilename() + " to UpYun " + upFilePath);
}
String filePath = StringUtils.removeEnd(ossDomain, "/") + upFilePath;
@ -96,13 +96,14 @@ public class UpYunFileHandler implements FileHandler {
return uploadResult;
} catch (Exception e) {
throw new FileUploadException("Failed to upload file " + file.getOriginalFilename() + " to UpYun", e);
throw new FileOperationException("Failed to upload file " + file.getOriginalFilename() + " to UpYun", e);
}
}
@Override
public boolean delete(String key) {
return false;
public void delete(String key) {
// TODO Handle file deletion
}
@Override

View File

@ -1,6 +1,6 @@
package cc.ryanc.halo.service;
import cc.ryanc.halo.exception.FileUploadException;
import cc.ryanc.halo.exception.FileOperationException;
import cc.ryanc.halo.model.dto.AttachmentOutputDTO;
import cc.ryanc.halo.model.entity.Attachment;
import cc.ryanc.halo.service.base.CrudService;
@ -30,7 +30,7 @@ public interface AttachmentService extends CrudService<Attachment, Integer> {
*
* @param file multipart file must not be null
* @return attachment info
* @throws FileUploadException throws when failed to filehandler the file
* @throws FileOperationException throws when failed to filehandler the file
*/
@NonNull
Attachment upload(@NonNull MultipartFile file);

View File

@ -66,4 +66,5 @@ public class FilenameUtils {
return filename.substring(dotLastIndex + 1);
}
}

View File

@ -0,0 +1,26 @@
package cc.ryanc.halo.utils;
import org.junit.Test;
import java.nio.file.Path;
import java.nio.file.Paths;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertThat;
/**
* Paths test.
*
* @author johnniang
* @date 3/27/19
*/
public class PathsTest {
@Test
public void getTest() {
Path path = Paths.get("/home/test/", "/upload/test.txt");
assertThat(path.toString(), equalTo("/home/test/upload/test.txt"));
assertThat(path.getParent().toString(), equalTo("/home/test/upload"));
}
}