未验证 提交 0dc75e29 编写于 作者: G guqing 提交者: GitHub

feat: add work dir backup options (#1494)

* feat: Add backup options

* feat: add sort for list backup items api

* refactor: rename varibles
上级 8c26430b
......@@ -6,8 +6,12 @@ import static run.halo.app.service.BackupService.BackupType.WHOLE_SITE;
import io.swagger.annotations.ApiOperation;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import javax.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.Resource;
......@@ -81,8 +85,19 @@ public class BackupController {
@PostMapping("work-dir")
@ApiOperation("Backups work directory")
@DisableOnCondition
public BackupDTO backupHalo() {
return backupService.backupWorkDirectory();
public BackupDTO backupHalo(@RequestBody List<String> options) {
return backupService.backupWorkDirectory(options);
}
@GetMapping("work-dir/options")
@ApiOperation("Gets items that can be backed up")
public List<String> listBackupItems() throws IOException {
return Files.list(Paths.get(haloProperties.getWorkDir()))
.map(Path::getFileName)
.filter(Objects::nonNull)
.map(Path::toString)
.sorted()
.collect(Collectors.toList());
}
@GetMapping("work-dir")
......
......@@ -32,11 +32,11 @@ public interface BackupService {
/**
* Zips work directory.
*
* @param options file or directory items to back up
* @return backup dto.
*/
@NonNull
BackupDTO backupWorkDirectory();
BackupDTO backupWorkDirectory(List<String> options);
/**
* Lists all backups.
......
......@@ -33,10 +33,12 @@ import org.springframework.core.io.UrlResource;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;
import run.halo.app.config.properties.HaloProperties;
import run.halo.app.event.options.OptionUpdatedEvent;
import run.halo.app.event.theme.ThemeUpdatedEvent;
import run.halo.app.exception.BadRequestException;
import run.halo.app.exception.NotFoundException;
import run.halo.app.exception.ServiceException;
import run.halo.app.handler.file.FileHandler;
......@@ -213,7 +215,10 @@ public class BackupServiceImpl implements BackupService {
}
@Override
public BackupDTO backupWorkDirectory() {
public BackupDTO backupWorkDirectory(List<String> options) {
if (CollectionUtils.isEmpty(options)) {
throw new BadRequestException("The options parameter is missing, at least one.");
}
// Zip work directory to temporary file
try {
// Create zip path for halo zip
......@@ -229,7 +234,17 @@ public class BackupServiceImpl implements BackupService {
// Zip halo
run.halo.app.utils.FileUtils
.zip(Paths.get(this.haloProperties.getWorkDir()), haloZipPath);
.zip(Paths.get(this.haloProperties.getWorkDir()), haloZipPath,
path -> {
for (String itemToBackup : options) {
Path backupItemPath =
Paths.get(this.haloProperties.getWorkDir()).resolve(itemToBackup);
if (path.startsWith(backupItemPath)) {
return true;
}
}
return false;
});
// Build backup dto
return buildBackupDto(BACKUP_RESOURCE_BASE_URI, haloZipPath);
......
......@@ -185,6 +185,23 @@ public class FileUtils {
}
}
/**
* Zips folder or file with filter.
*
* @param pathToZip file path to zip must not be null
* @param pathOfArchive zip file path to archive must not be null
* @param filter folder or file filter
* @throws IOException throws when failed to access file to be zipped
*/
public static void zip(@NonNull Path pathToZip, @NonNull Path pathOfArchive,
@Nullable Predicate<Path> filter) throws IOException {
try (OutputStream outputStream = Files.newOutputStream(pathOfArchive)) {
try (ZipOutputStream zipOut = new ZipOutputStream(outputStream)) {
zip(pathToZip, zipOut, filter);
}
}
}
/**
* Zips folder or file.
*
......@@ -198,6 +215,20 @@ public class FileUtils {
zip(pathToZip, pathToZip.getFileName().toString(), zipOut);
}
/**
* Zips folder or file with filter.
*
* @param pathToZip file path to zip must not be null
* @param zipOut zip output stream must not be null
* @param filter directory or file filter
* @throws IOException throws when failed to access file to be zipped
*/
public static void zip(@NonNull Path pathToZip, @NonNull ZipOutputStream zipOut,
Predicate<Path> filter) throws IOException {
// Zip file
zip(pathToZip, pathToZip.getFileName().toString(), zipOut, filter);
}
/**
* Zips folder or file.
*
......@@ -208,6 +239,20 @@ public class FileUtils {
*/
private static void zip(@NonNull Path fileToZip, @NonNull String fileName,
@NonNull ZipOutputStream zipOut) throws IOException {
zip(fileToZip, fileName, zipOut, null);
}
/**
* Zips folder or file with path filter.
*
* @param fileToZip file path to zip must not be null
* @param fileName file name must not be blank
* @param zipOut zip output stream must not be null
* @param filter directory or file filter
* @throws IOException throws when failed to access file to be zipped
*/
private static void zip(@NonNull Path fileToZip, @NonNull String fileName,
@NonNull ZipOutputStream zipOut, @Nullable Predicate<Path> filter) throws IOException {
if (Files.isDirectory(fileToZip)) {
log.debug("Try to zip folder: [{}]", fileToZip);
// Append with '/' if missing
......@@ -222,10 +267,12 @@ public class FileUtils {
try (Stream<Path> subPathStream = Files.list(fileToZip)) {
// There should not use foreach for stream as internal zip method will throw
// IOException
List<Path> subFiles = subPathStream.collect(Collectors.toList());
List<Path> subFiles =
filter != null ? subPathStream.filter(filter).collect(Collectors.toList())
: subPathStream.collect(Collectors.toList());
for (Path subFileToZip : subFiles) {
// Zip children
zip(subFileToZip, folderName + subFileToZip.getFileName(), zipOut);
zip(subFileToZip, folderName + subFileToZip.getFileName(), zipOut, filter);
}
}
} else {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册