From a4fc24b20d685320e34c71913a20bcfc056ce484 Mon Sep 17 00:00:00 2001
From: Kai Reinhard <K.Reinhard@micromata.de>
Date: Mon, 17 Dec 2018 22:59:31 +0000
Subject: [PATCH] Handling of recreating files and directories works now fine (opens a file dialog with the restored items).
---
borgbutler-webapp/src/components/views/archives/FileListEntry.jsx | 11 ++-
borgbutler-core/src/main/java/de/micromata/borgbutler/config/Configuration.java | 33 +++++++++++
borgbutler-core/src/main/java/de/micromata/borgbutler/BorgCommands.java | 22 ++++++-
borgbutler-server/src/main/java/de/micromata/borgbutler/server/rest/ArchivesRest.java | 93 +++++++++++++++++++-----------
4 files changed, 118 insertions(+), 41 deletions(-)
diff --git a/borgbutler-core/src/main/java/de/micromata/borgbutler/BorgCommands.java b/borgbutler-core/src/main/java/de/micromata/borgbutler/BorgCommands.java
index c2bbbda..0c8bfbe 100644
--- a/borgbutler-core/src/main/java/de/micromata/borgbutler/BorgCommands.java
+++ b/borgbutler-core/src/main/java/de/micromata/borgbutler/BorgCommands.java
@@ -9,6 +9,7 @@
import de.micromata.borgbutler.json.JsonUtils;
import de.micromata.borgbutler.json.borg.*;
import de.micromata.borgbutler.utils.DateUtils;
+import de.micromata.borgbutler.utils.ReplaceUtils;
import lombok.Setter;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.exec.CommandLine;
@@ -20,6 +21,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import javax.naming.Context;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
@@ -157,12 +159,24 @@
return content;
}
- public static Path extractFiles(BorgRepoConfig repoConfig, String archive, String path) throws IOException {
- Path tempDirWithPrefix = Files.createTempDirectory("borgbutler-extract-");
- Context context = new Context().setWorkingDir(tempDirWithPrefix.toFile()).setRepoConfig(repoConfig)
+ /**
+ * Stores the file in a subdirectory named with the repos display name.
+ * @param restoreHomeDir
+ * @param repoConfig
+ * @param archive
+ * @param path
+ * @return Used sub directory with the restored content.
+ * @throws IOException
+ */
+ public static File extractFiles(File restoreHomeDir, BorgRepoConfig repoConfig, String archive, String path) throws IOException {
+ File restoreDir = new File(restoreHomeDir, ReplaceUtils.encodeFilename(repoConfig.getDisplayName(), true));
+ if (!restoreDir.exists()) {
+ restoreDir.mkdirs();
+ }
+ Context context = new Context().setWorkingDir(restoreDir).setRepoConfig(repoConfig)
.setCommand("extract").setArchive(archive).setArgs(path);
execute(context);
- return tempDirWithPrefix;
+ return restoreDir;
}
private static String execute(Context context) {
diff --git a/borgbutler-core/src/main/java/de/micromata/borgbutler/config/Configuration.java b/borgbutler-core/src/main/java/de/micromata/borgbutler/config/Configuration.java
index cc85168..8aca808 100644
--- a/borgbutler-core/src/main/java/de/micromata/borgbutler/config/Configuration.java
+++ b/borgbutler-core/src/main/java/de/micromata/borgbutler/config/Configuration.java
@@ -1,13 +1,23 @@
package de.micromata.borgbutler.config;
+import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
+import de.micromata.borgbutler.BorgCommands;
import lombok.Getter;
import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import java.io.File;
import java.util.ArrayList;
import java.util.List;
public class Configuration {
+ private Logger log = LoggerFactory.getLogger(Configuration.class);
+ /**
+ * Default dir name for restoring archives.
+ */
+ private static final String RESTORE_DIRNAME = "restore";
@Getter
private String borgCommand = "borg";
/**
@@ -17,6 +27,15 @@
@JsonProperty("cache_archive_content_max_disc_size_mb")
private int cacheArchiveContentMaxDiscSizeMB = 100;
+ /**
+ * Default is restore inside BorgButler's home dir (~/.borgbutler/restore).
+ */
+ @Getter
+ @JsonProperty("restore_dir")
+ private String restoreDirPath;
+ @JsonIgnore
+ private File restoreHomeDir;
+
@Getter
@JsonProperty("repo-configs")
private List<BorgRepoConfig> repoConfigs = new ArrayList<>();
@@ -36,4 +55,18 @@
}
return null;
}
+
+ public File getRestoreHomeDir() {
+ if (restoreHomeDir == null) {
+ if (StringUtils.isNotBlank(restoreDirPath)) {
+ restoreHomeDir = new File(restoreDirPath);
+ } else {
+ restoreHomeDir = new File(ConfigurationHandler.getInstance().getWorkingDir(), RESTORE_DIRNAME);
+ }
+ if (!restoreHomeDir.exists()) {
+ log.info("Creating dir '" + restoreHomeDir.getAbsolutePath() + "' for restoring backup files and directories.");
+ }
+ }
+ return restoreHomeDir;
+ }
}
diff --git a/borgbutler-server/src/main/java/de/micromata/borgbutler/server/rest/ArchivesRest.java b/borgbutler-server/src/main/java/de/micromata/borgbutler/server/rest/ArchivesRest.java
index eb9812d..f5e3a87 100644
--- a/borgbutler-server/src/main/java/de/micromata/borgbutler/server/rest/ArchivesRest.java
+++ b/borgbutler-server/src/main/java/de/micromata/borgbutler/server/rest/ArchivesRest.java
@@ -26,6 +26,7 @@
import java.awt.*;
import java.io.File;
import java.io.IOException;
+import java.nio.file.Files;
import java.util.List;
@Path("/archives")
@@ -79,14 +80,14 @@
}
@GET
- @Path("/download")
+ @Path("/restore")
@Produces(MediaType.APPLICATION_OCTET_STREAM)
/**
* @param archiveId
- * @param fileNumber The fileNumber of the file in the archive served by BorgButler's
+ * @param fileNumber The fileNumber of the file or directory in the archive served by BorgButler's
* {@link #getArchiveFileLIst(String, String, String, boolean, boolean)}
*/
- public Response downloadFilebyPath(@QueryParam("archiveId") String archiveId, @QueryParam("fileNumber") int fileNumber) {
+ public Response restore(@QueryParam("archiveId") String archiveId, @QueryParam("fileNumber") int fileNumber) {
log.info("Requesting file #" + fileNumber + " of archive '" + archiveId + "'.");
FileSystemFilter filter = new FileSystemFilter().setFileNumber(fileNumber);
List<BorgFilesystemItem> items = ButlerCache.getInstance().getArchiveContent(archiveId, false,
@@ -94,7 +95,7 @@
if (CollectionUtils.isEmpty(items)) {
log.error("Requested file #" + fileNumber + " not found in archive '" + archiveId
+ ". (May-be the archive content isn't yet loaded to the cache.");
- Response.ResponseBuilder builder = Response.status(404);
+ Response.ResponseBuilder builder = Response.status(Response.Status.NOT_FOUND);
return builder.build();
}
if (items.size() != 1) {
@@ -103,18 +104,63 @@
Response.ResponseBuilder builder = Response.status(404);
return builder.build();
}
- BorgFilesystemItem item = items.get(0);
Archive archive = ButlerCache.getInstance().getArchive(archiveId);
if (archive == null) {
- Response.ResponseBuilder builder = Response.status(404);
+ Response.ResponseBuilder builder = Response.status(Response.Status.NOT_FOUND);
return builder.build();
}
BorgRepoConfig repoConfig = ConfigurationHandler.getConfiguration().getRepoConfig(archive.getRepoId());
- java.nio.file.Path path = null;
- java.nio.file.Path tempDir = null;
try {
- tempDir = BorgCommands.extractFiles(repoConfig, archive.getName(), item.getPath());
- openFileBrowser(tempDir);
+ BorgFilesystemItem item = items.get(0);
+ File restoreHomeDir = ConfigurationHandler.getConfiguration().getRestoreHomeDir();
+ File restoreDir = BorgCommands.extractFiles(restoreHomeDir, repoConfig, archive.getName(), item.getPath());
+ List<java.nio.file.Path> files = DirUtils.listFiles(restoreDir.toPath());
+ if (CollectionUtils.isEmpty(files)) {
+ log.error("No files extracted.");
+ Response.ResponseBuilder builder = Response.status(Response.Status.NOT_FOUND);
+ return builder.build();
+ }
+ openFileBrowser(new File(restoreDir, item.getPath()));
+ Response.ResponseBuilder builder = Response.status(Response.Status.ACCEPTED);
+ return builder.build();
+ } catch (IOException ex) {
+ log.error("No file extracted: " + ex.getMessage(), ex);
+ Response.ResponseBuilder builder = Response.status(Response.Status.NOT_FOUND);
+ return builder.build();
+ }
+ }
+
+ public void openFileBrowser(File directory) {
+ if (Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.BROWSE_FILE_DIR)) {
+ Desktop.getDesktop().browseFileDirectory(directory);
+ }
+ }
+
+ private Response handleRestoredFiles(BorgRepoConfig repoConfig, Archive archive) {
+ // Todo: Handle download from single files as well as download of zip archive (if BorgButler runs remote).
+ return null;
+ /* File file = path.toFile();
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ try {
+ FileUtils.copyFile(file, baos);
+ } catch (IOException ex) {
+ log.error(ex.getMessage(), ex);
+ }
+ BorgFilesystemItem item = items.get(0);
+ file = new File(item.getPath());
+ byte[] byteArray = baos.toByteArray();//result.getAsByteArrayOutputStream().toByteArray();
+ Response.ResponseBuilder builder = Response.ok(byteArray);
+ builder.header("Content-Disposition", "attachment; filename=" + file.getName());
+ // Needed to get the Content-Disposition by client:
+ builder.header("Access-Control-Expose-Headers", "Content-Disposition");
+ Response response = builder.build();
+ return response;
+
+ try {
+ //java.nio.file.Path tempDirWithPrefix = Files.createTempDirectory("borgbutler-extract-");
+ File restoreHomeDir = ConfigurationHandler.getConfiguration().getRestoreHomeDir();
+ File restoreDir = BorgCommands.extractFiles(restoreHomeDir, repoConfig, archive.getName(), item.getPath());
+ openFileBrowser(restoreDir);
List<java.nio.file.Path> files = DirUtils.listFiles(tempDir);
if (CollectionUtils.isEmpty(files)) {
log.error("No file extracted.");
@@ -122,39 +168,18 @@
return builder.build();
}
path = files.get(0);
- File file = path.toFile();
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- try {
- FileUtils.copyFile(file, baos);
- } catch (IOException ex) {
- log.error(ex.getMessage(), ex);
- }
- file = new File(item.getPath());
- byte[] byteArray = baos.toByteArray();//result.getAsByteArrayOutputStream().toByteArray();
- Response.ResponseBuilder builder = Response.ok(byteArray);
- builder.header("Content-Disposition", "attachment; filename=" + file.getName());
- // Needed to get the Content-Disposition by client:
- builder.header("Access-Control-Expose-Headers", "Content-Disposition");
- Response response = builder.build();
- return response;
} catch (IOException ex) {
log.error("No file extracted: " + ex.getMessage(), ex);
Response.ResponseBuilder builder = Response.status(404);
return builder.build();
} finally {
-/* if (tempDir != null) {
+ if (tempDir != null) {
try {
FileUtils.deleteDirectory(tempDir.toFile());
} catch (IOException ex) {
log.error("Error while trying to delete temporary directory '" + tempDir.toString() + "': " + ex.getMessage(), ex);
}
- }*/
- }
- }
-
- public static void openFileBrowser(java.nio.file.Path path) {
- if (Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.BROWSE_FILE_DIR)) {
- Desktop.getDesktop().browseFileDirectory(path.toFile());
- }
+ }
+ }*/
}
}
diff --git a/borgbutler-webapp/src/components/views/archives/FileListEntry.jsx b/borgbutler-webapp/src/components/views/archives/FileListEntry.jsx
index ec8f51d..41a5511 100644
--- a/borgbutler-webapp/src/components/views/archives/FileListEntry.jsx
+++ b/borgbutler-webapp/src/components/views/archives/FileListEntry.jsx
@@ -7,20 +7,25 @@
function download(archiveId, fileNumber) {
let filename;
- fetch(getRestServiceUrl('archives/download', {
+ fetch(getRestServiceUrl('archives/restore', {
archiveId: archiveId,
fileNumber: fileNumber
}))
.then(response => {
+ if (response.status === 202) { // ACCEPTED
+ // No download wanted (file or path was only restored on server).
+ return undefined;
+ }
if (!response.ok) {
throw new Error(response.statusText);
}
-
filename = getResponseHeaderFilename(response.headers.get('Content-Disposition'));
return response.blob();
})
.then(blob => {
- fileDownload(blob, filename)
+ if (filename) {
+ fileDownload(blob, filename);
+ }
})
.catch(error => {
console.log(error.toString());
--
Gitblit v1.10.0