mirror of https://github.com/halo-dev/halo
Add some useful features to FileUtils
parent
3d17e0f786
commit
ef417a2c14
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue