From 4ecd0e5178bc4d5895aa200cdc4c63750b0cb5cc Mon Sep 17 00:00:00 2001 From: yanglang Date: Thu, 3 Sep 2020 11:01:36 +0800 Subject: [PATCH] feat #增加自定义文件操作工具 --- pom.xml | 17 ++++++++++++----- src/main/java/com/irrigation/icl/utils/LocalFileUtils.java | 376 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 388 insertions(+), 5 deletions(-) create mode 100644 src/main/java/com/irrigation/icl/utils/LocalFileUtils.java diff --git a/pom.xml b/pom.xml index e29df33..b9d54c3 100644 --- a/pom.xml +++ b/pom.xml @@ -16,20 +16,27 @@ 1.18.10 1.11 28.1-jre - 1.7.24 + 1.7.25 1.2.49 5.0.9.RELEASE 5.0.9.RELEASE 2.6.11 + 2.7 + + + + + + + - org.slf4j - slf4j-api - ${slf4j.version} - provided + commons-io + commons-io + ${commons-io.version} com.google.guava diff --git a/src/main/java/com/irrigation/icl/utils/LocalFileUtils.java b/src/main/java/com/irrigation/icl/utils/LocalFileUtils.java new file mode 100644 index 0000000..7ebfe44 --- /dev/null +++ b/src/main/java/com/irrigation/icl/utils/LocalFileUtils.java @@ -0,0 +1,376 @@ +package com.irrigation.icl.utils; + + +import com.irrigation.icl.exception.ContextRuntimeException; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.io.FileUtils; +import org.springframework.util.Assert; +import org.springframework.util.StringUtils; +import org.springframework.web.multipart.MultipartFile; + +import java.io.*; +import java.nio.charset.Charset; +import java.util.Arrays; +import java.util.Enumeration; +import java.util.List; +import java.util.Optional; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; +import java.util.zip.ZipOutputStream; + +/** + * @description: + * @Author: yangLang + * @CreateDate: 2020/9/2 14:39 + */ +@Slf4j +public class LocalFileUtils { + + + /** + * 文件后缀分隔符 + */ + public static final String FILE_SUFFIX_SEPARATOR = "."; + + /** + * 编码方式 + */ + public final static String DEFAULT_CHARSET = "GBK"; + + private LocalFileUtils() { + } + + /** + * 创建文件 + * + * @param parentFile 辅机目录 + * @param fileName 文件名称 + * @return java.io.File + * @Author yangLang + * @Date 15:30 2020/9/2 + */ + public static File getFile(File parentFile, String fileName) { + Assert.notNull(fileName, "Depending create file is null"); + File file; + if (ObjectUtils.isNull(parentFile)) { + file = new File(fileName); + } else { + file = new File(parentFile, fileName); + } + if (!file.exists()) { + try { + file.createNewFile(); + } catch (IOException e) { + log.error("Create File Failed:{}", e.getMessage()); + } + } + Assert.isTrue(file.exists(), "Create file failed"); + return file; + } + + /** + * 创建目录 + * + * @param parentFile 父目录 + * @param filePath 目录的指定路径 + * @return java.io.File + * @Author yangLang + * @Date 15:22 2020/9/2 + */ + public static File getDirectoryFile(File parentFile, String filePath) { + Assert.notNull(filePath, "Depending created file is null"); + File file; + if (ObjectUtils.isNull(parentFile)) { + file = new File(filePath); + } else { + file = new File(parentFile, filePath); + } + if (!file.exists()) { + file.mkdirs(); + } + Assert.isTrue(file.exists(), "Created file failed"); + return file; + } + + /** + * 获取文件的后缀名 + * + * @param file 文件名 + * @param isContainSuffixSeparator 是否包含文件后缀分隔符 + * @return java.lang.String + * @Author yangLang + * @Date 16:01 2020/9/2 + */ + public static String getFileExtension(File file, boolean isContainSuffixSeparator) { + Assert.notNull(file, "File is null"); + String fileName = file.getName(); + Assert.notNull(fileName, "File is not exist"); + int index = fileName.lastIndexOf(FILE_SUFFIX_SEPARATOR); + if (index == -1 || index >= fileName.length()) { + return null; + } + if (!isContainSuffixSeparator) { + index++; + } + return fileName.substring(index); + } + + /** + * 获取文件的后缀名 + * + * @param filePath 文件路径 + * @param isContainSuffixSeparator 是否包含文件后缀分隔符 + * @return java.lang.String + * @Author yangLang + * @Date 16:02 2020/9/2 + */ + public static String getFilePathExtension(String filePath, boolean isContainSuffixSeparator) { + Assert.notNull(filePath, "File is null"); + int index = filePath.lastIndexOf(FILE_SUFFIX_SEPARATOR); + if (index == -1 || index >= filePath.length()) { + return null; + } + if (!isContainSuffixSeparator) { + index++; + } + return filePath.substring(index); + } + + /** + * 获取 MultipartFile 文件后缀 + * + * @param file 文件 + * @param isContainSuffixSeparator 是否包含文件后缀分隔符 + * @return java.lang.String 后缀字符串 + * @Author yangLang + * @Date 9:39 2020/9/3 + */ + public static String getMultipartFileExtension(MultipartFile file, boolean isContainSuffixSeparator) { + Assert.notNull(file, "File is null"); + int index = file.getOriginalFilename().lastIndexOf(FILE_SUFFIX_SEPARATOR); + if (index == -1 || index >= file.getOriginalFilename().length()) { + return null; + } + if (!isContainSuffixSeparator) { + index++; + } + return file.getOriginalFilename().substring(index); + } + + /** + * 判断文件是否为期望的文件格式(不包含文件后缀分隔符) + * + * @param file 文件 + * @param expectExtension 期望的文件格式 + * @return boolean + * @Author yangLang + * @Date 16:17 2020/9/2 + */ + public static boolean judgeFileExtension(File file, String expectExtension) { + Assert.notNull(file, "Depend judge file is null"); + Assert.notNull(expectExtension, "The expect extension is null"); + String fileExtension = getFileExtension(file, false); + return expectExtension.equalsIgnoreCase(fileExtension); + } + + /** + * 判断文件路径是否为期望的文件格式(不包含文件后缀分隔符) + * + * @param filePath 文件路径 + * @param expectExtension 期望的文件格式 + * @return boolean + * @Author yangLang + * @Date 9:42 2020/9/3 + */ + public static boolean judgeFilePathExtension(String filePath, String expectExtension) { + Assert.notNull(filePath, "Depend judge file is null"); + Assert.notNull(expectExtension, "The expect extension is null"); + String fileExtension = getFilePathExtension(filePath, false); + return expectExtension.equalsIgnoreCase(fileExtension); + } + + /** + * 判断文件是否为期望的文件格式(不包含文件后缀分隔符) + * + * @param file 文件 + * @param expectExtension 期望的格式 + * @return boolean + * @Author yangLang + * @Date 16:19 2020/9/2 + */ + public static boolean judgeMultipartFileExtension(MultipartFile file, String expectExtension) { + Assert.notNull(file, "Depend judge file is null"); + Assert.notNull(expectExtension, "The expect extension is null"); + String fileExtension = getFilePathExtension(file.getOriginalFilename(), false); + return expectExtension.equalsIgnoreCase(fileExtension); + } + + /** + * multipartFile 转 File + * + * @param multipartFile 带转换的 multipartFile 文件 + * @param parentFile 转换完成后的文件所在的目录 + * @return java.io.File + * @Author yangLang + * @Date 17:03 2020/9/2 + */ + public static File multipartFile2File(MultipartFile multipartFile, File parentFile) { + Assert.notNull(multipartFile, "Depend trances file is null"); + Assert.isTrue(parentFile.isDirectory(), "Parent File not a directory"); + File tempFile = getFile(parentFile, multipartFile.getOriginalFilename()); + try (InputStream inputStream = multipartFile.getInputStream()) { + FileUtils.copyInputStreamToFile(inputStream, tempFile); + } catch (IOException e) { + throw new ContextRuntimeException("文件转换失败"); + } + return tempFile; + } + + /** + * 解压文件到指定目录,解压后的文件名和之前一致 + * + * @param unZipFile 解压文件 + * @param parentFile 解压文件后所置的目录 + * @param encode 编码方式,默认是GBK + * @param isDeleteZipFile 是否需要删除压缩文件,默认不删除 + * @return void + * @Author yangLang + * @Date 17:14 2020/9/2 + */ + public static void unZipFile(File unZipFile, File parentFile, String encode, Boolean isDeleteZipFile) { + Assert.notNull(parentFile, "Unzip file's parent file is null"); + try (ZipFile zip = new ZipFile(unZipFile, Charset.forName(Optional.ofNullable(encode).orElse(DEFAULT_CHARSET)))) { + FileOutputStream out = null; + for (Enumeration entries = zip.entries(); entries.hasMoreElements(); ) { + ZipEntry entry = entries.nextElement(); + String zipEntryName = entry.getName(); + try (InputStream in = zip.getInputStream(entry)) { + int index = zipEntryName.lastIndexOf(StringUtils.cleanPath(File.separator)); + File file; + // 如果是文件夹,只创建文件夹,直接返回,无需读写文件 + if (index == zipEntryName.length() - 1 || index == -1) { + getDirectoryFile(parentFile, zipEntryName); + continue; + } else { + // 获取文件的名称 + String substring = zipEntryName.substring(0, index); + // 创建父文件目录 + file = getDirectoryFile(parentFile, substring); + // 创建文件 + file = getFile(file, zipEntryName.substring(index + 1)); + } + out = new FileOutputStream(file); + byte[] buf1 = new byte[1024]; + int len; + while ((len = in.read(buf1)) > 0) { + out.write(buf1, 0, len); + } + } finally { + if (out != null) { + out.flush(); + out.close(); + } + } + } + } catch (IOException e) { + throw new ContextRuntimeException("File = " + unZipFile.getName() + " unzip failed."); + } + if (Optional.ofNullable(isDeleteZipFile).orElse(Boolean.FALSE)) { + FileUtils.deleteQuietly(unZipFile); + } + } + + /** + * 压缩文件 + * + * @param zipFiles 待压缩的文件 + * @param parentFile 压缩完成的文件所在目录 + * @param isDeleteSourcesFile 是否需要删除压缩前的源文件 + * @param zipFileName 压缩完成后的文件名称 + * @return java.io.File 压缩完成的文件 + * @Author yangLang + * @Date 17:10 2020/9/2 + */ + public static File zipFile(List zipFiles, File parentFile, String zipFileName, Boolean isDeleteSourcesFile) { + Assert.isTrue(ObjectUtils.nonEmpty(zipFiles), "Depending compress file is null"); + Assert.notNull(zipFileName, "Compress file name is null"); + Assert.notNull(parentFile, "Parent file of unzip file is null"); + File newFile = getFile(parentFile, zipFileName); + Assert.notNull(newFile, "Zip file create failed"); + try (FileOutputStream fos = new FileOutputStream(newFile); + ZipOutputStream zos = new ZipOutputStream(fos)) { + zipFiles.stream().forEach(item -> writeZip(item, "", zos)); + } catch (IOException e) { + log.error("Failed to create compressed file:{}", e.getMessage()); + } + if (Optional.ofNullable(isDeleteSourcesFile).orElse(Boolean.FALSE)) { + zipFiles.stream().forEach(item -> { + try { + FileUtils.deleteDirectory(item); + } catch (IOException e) { + log.error("File = {} delete failed", item.getAbsolutePath()); + } + }); + } + return newFile; + } + + /** + * 写压缩文件 + * + * @param file 待压缩的文件夹 + * @param parentPath 父文件路径 + * @param zos 压缩流 + * @return void + * @Author yangLang + * @Date 16:21 2020/8/6 + */ + private static void writeZip(File file, String parentPath, ZipOutputStream zos) { + if (!file.exists()) { + log.error("File = {} does not exist", file.getAbsolutePath()); + return; + } + if (!file.isDirectory()) { + zipWrite2File(file, parentPath, zos); + return; + } + File[] subFiles = file.listFiles(); + String subParentPath = parentPath + file.getName() + File.separator; + // 空目录则创建当前目录 + if (subFiles.length == 0) { + try { + zos.putNextEntry(new ZipEntry(subParentPath)); + } catch (IOException e) { + log.warn("{} Folder is empty", subParentPath); + } + return; + } + // 如果目录下包含文件,则递归压缩子文件 + Arrays.stream(subFiles).forEach(item -> writeZip(item, subParentPath, zos)); + } + + /** + * 压缩文件的时候写文件 + * + * @param file 文件 + * @param parentPath 父目录 + * @param zos 压缩流 + * @return void + * @Author yangLang + * @Date 16:29 2020/8/6 + */ + private static void zipWrite2File(File file, String parentPath, ZipOutputStream zos) { + ZipEntry ze = new ZipEntry(parentPath + file.getName()); + try (FileInputStream fis = new FileInputStream(file)) { + zos.putNextEntry(ze); + byte[] content = new byte[1024]; + int len; + while ((len = fis.read(content)) != -1) { + zos.write(content, 0, len); + zos.flush(); + } + } catch (Exception e) { + log.error("Failed to compress file = {}:{}", file.getName(), e.getMessage()); + } + } +} -- libgit2 0.21.4