Add some useful features to FileUtils

pull/146/head
johnniang 2019-04-19 09:36:20 +08:00
parent 3d17e0f786
commit ef417a2c14
1 changed files with 111 additions and 4 deletions

View File

@ -2,6 +2,7 @@ package run.halo.app.utils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import run.halo.app.exception.ForbiddenException;
@ -11,6 +12,7 @@ import java.io.InputStream;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.Comparator;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
/**
@ -68,6 +70,86 @@ public class FileUtils {
.forEach(File::delete);
}
/**
* Unzip content to the target path.
*
* @param zis zip input stream must not be null
* @param targetPath target path must not be null and not empty
* @throws IOException
*/
public static void unzip(@NonNull ZipInputStream zis, @NonNull Path targetPath) throws IOException {
Assert.notNull(zis, "Zip input stream must not be null");
Assert.notNull(targetPath, "Target path must not be null");
// Create path if absent
createIfAbsent(targetPath);
// Must be empty
mustBeEmpty(targetPath);
ZipEntry zipEntry = zis.getNextEntry();
while (zipEntry != null) {
// Resolve the entry path
Path entryPath = targetPath.resolve(zipEntry.getName());
// Check directory
FileUtils.checkDirectoryTraversal(targetPath, entryPath);
if (zipEntry.isDirectory()) {
// Create directories
Files.createDirectories(entryPath);
} else {
// Copy file
Files.copy(zis, entryPath);
}
zipEntry = zis.getNextEntry();
}
}
/**
* Creates directories if absent.
*
* @param path path must not be null
* @throws IOException
*/
public static void createIfAbsent(@NonNull Path path) throws IOException {
Assert.notNull(path, "Path must not be null");
if (Files.notExists(path)) {
// Create directories
Files.createDirectories(path);
log.debug("Created directory: [{}]", path);
}
}
/**
* Checks if the given path is empty.
*
* @param path path must not be null
* @return true if the given path is empty; false otherwise
* @throws IOException
*/
public static boolean isEmpty(@NonNull Path path) throws IOException {
Assert.notNull(path, "Path must not be null");
return Files.list(path).count() == 0;
}
/**
* The given path must be empty.
*
* @param path path must not be null
* @throws IOException
*/
public static void mustBeEmpty(@NonNull Path path) throws IOException {
if (!isEmpty(path)) {
throw new DirectoryNotEmptyException("Target directory: " + path + " was not empty");
}
}
/**
* Checks directory traversal vulnerability.
*
@ -105,18 +187,28 @@ public class FileUtils {
throw new ForbiddenException("You cannot access " + pathToCheck).setErrorData(pathToCheck);
}
public static void closeQuietly(InputStream inputStream) {
/**
* Closes input stream quietly.
*
* @param inputStream input stream
*/
public static void closeQuietly(@Nullable InputStream inputStream) {
try {
if (inputStream != null) {
inputStream.close();
}
} catch (IOException e) {
// Ignore this exception
log.error("Failed to close input stream", e);
log.warn("Failed to close input stream", e);
}
}
public static void closeQuietly(ZipInputStream zipInputStream) {
/**
* Closes zip input stream quietly.
*
* @param zipInputStream zip input stream
*/
public static void closeQuietly(@Nullable ZipInputStream zipInputStream) {
try {
if (zipInputStream != null) {
zipInputStream.closeEntry();
@ -124,7 +216,22 @@ public class FileUtils {
}
} catch (IOException e) {
// Ignore this exception
log.error("Failed to close zip input stream", e);
log.warn("Failed to close zip input stream", e);
}
}
/**
* Deletes folder quietly.
*
* @param deletingPath deleting path must not be null
*/
public static void deleteFolderQuietly(@NonNull Path deletingPath) {
try {
if (deletingPath != null) {
FileUtils.deleteFolder(deletingPath);
}
} catch (IOException e) {
log.warn("Failed to delete " + deletingPath);
}
}
}