Commit 43a803b033531692671d15bac6db3ed77fa0e194

Authored by zhangchuanxi
2 parents f88bff42 4ecd0e51

Merge branch 'dev2.0' into 'master'

feat #增加自定义文件操作工具

增加自定义文件操作工具

See merge request !1
... ... @@ -16,20 +16,27 @@
16 16 <lombok.version>1.18.10</lombok.version>
17 17 <commons-codec.version>1.11</commons-codec.version>
18 18 <guava.vsersion>28.1-jre</guava.vsersion>
19   - <slf4j.version>1.7.24</slf4j.version>
  19 + <slf4j.version>1.7.25</slf4j.version>
20 20 <fastjson.version>1.2.49</fastjson.version>
21 21 <spring-web.version>5.0.9.RELEASE</spring-web.version>
22 22 <spring-security-core.version>5.0.9.RELEASE</spring-security-core.version>
23 23 <ehcache.version>2.6.11</ehcache.version>
  24 + <commons-io.version>2.7</commons-io.version>
24 25 </properties>
25 26  
26 27  
27 28 <dependencies>
  29 +<!-- <dependency>-->
  30 +<!-- <groupId>org.slf4j</groupId>-->
  31 +<!-- <artifactId>slf4j-api</artifactId>-->
  32 +<!-- <version>${slf4j.version}</version>-->
  33 +<!-- <scope>provided</scope>-->
  34 +<!-- </dependency>-->
  35 + <!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
28 36 <dependency>
29   - <groupId>org.slf4j</groupId>
30   - <artifactId>slf4j-api</artifactId>
31   - <version>${slf4j.version}</version>
32   - <scope>provided</scope>
  37 + <groupId>commons-io</groupId>
  38 + <artifactId>commons-io</artifactId>
  39 + <version>${commons-io.version}</version>
33 40 </dependency>
34 41 <dependency>
35 42 <groupId>com.google.guava</groupId>
... ...
src/main/java/com/irrigation/icl/utils/LocalFileUtils.java 0 → 100644
  1 +package com.irrigation.icl.utils;
  2 +
  3 +
  4 +import com.irrigation.icl.exception.ContextRuntimeException;
  5 +import lombok.extern.slf4j.Slf4j;
  6 +import org.apache.commons.io.FileUtils;
  7 +import org.springframework.util.Assert;
  8 +import org.springframework.util.StringUtils;
  9 +import org.springframework.web.multipart.MultipartFile;
  10 +
  11 +import java.io.*;
  12 +import java.nio.charset.Charset;
  13 +import java.util.Arrays;
  14 +import java.util.Enumeration;
  15 +import java.util.List;
  16 +import java.util.Optional;
  17 +import java.util.zip.ZipEntry;
  18 +import java.util.zip.ZipFile;
  19 +import java.util.zip.ZipOutputStream;
  20 +
  21 +/**
  22 + * @description:
  23 + * @Author: yangLang
  24 + * @CreateDate: 2020/9/2 14:39
  25 + */
  26 +@Slf4j
  27 +public class LocalFileUtils {
  28 +
  29 +
  30 + /**
  31 + * 文件后缀分隔符
  32 + */
  33 + public static final String FILE_SUFFIX_SEPARATOR = ".";
  34 +
  35 + /**
  36 + * 编码方式
  37 + */
  38 + public final static String DEFAULT_CHARSET = "GBK";
  39 +
  40 + private LocalFileUtils() {
  41 + }
  42 +
  43 + /**
  44 + * 创建文件
  45 + *
  46 + * @param parentFile 辅机目录
  47 + * @param fileName 文件名称
  48 + * @return java.io.File
  49 + * @Author yangLang
  50 + * @Date 15:30 2020/9/2
  51 + */
  52 + public static File getFile(File parentFile, String fileName) {
  53 + Assert.notNull(fileName, "Depending create file is null");
  54 + File file;
  55 + if (ObjectUtils.isNull(parentFile)) {
  56 + file = new File(fileName);
  57 + } else {
  58 + file = new File(parentFile, fileName);
  59 + }
  60 + if (!file.exists()) {
  61 + try {
  62 + file.createNewFile();
  63 + } catch (IOException e) {
  64 + log.error("Create File Failed:{}", e.getMessage());
  65 + }
  66 + }
  67 + Assert.isTrue(file.exists(), "Create file failed");
  68 + return file;
  69 + }
  70 +
  71 + /**
  72 + * 创建目录
  73 + *
  74 + * @param parentFile 父目录
  75 + * @param filePath 目录的指定路径
  76 + * @return java.io.File
  77 + * @Author yangLang
  78 + * @Date 15:22 2020/9/2
  79 + */
  80 + public static File getDirectoryFile(File parentFile, String filePath) {
  81 + Assert.notNull(filePath, "Depending created file is null");
  82 + File file;
  83 + if (ObjectUtils.isNull(parentFile)) {
  84 + file = new File(filePath);
  85 + } else {
  86 + file = new File(parentFile, filePath);
  87 + }
  88 + if (!file.exists()) {
  89 + file.mkdirs();
  90 + }
  91 + Assert.isTrue(file.exists(), "Created file failed");
  92 + return file;
  93 + }
  94 +
  95 + /**
  96 + * 获取文件的后缀名
  97 + *
  98 + * @param file 文件名
  99 + * @param isContainSuffixSeparator 是否包含文件后缀分隔符
  100 + * @return java.lang.String
  101 + * @Author yangLang
  102 + * @Date 16:01 2020/9/2
  103 + */
  104 + public static String getFileExtension(File file, boolean isContainSuffixSeparator) {
  105 + Assert.notNull(file, "File is null");
  106 + String fileName = file.getName();
  107 + Assert.notNull(fileName, "File is not exist");
  108 + int index = fileName.lastIndexOf(FILE_SUFFIX_SEPARATOR);
  109 + if (index == -1 || index >= fileName.length()) {
  110 + return null;
  111 + }
  112 + if (!isContainSuffixSeparator) {
  113 + index++;
  114 + }
  115 + return fileName.substring(index);
  116 + }
  117 +
  118 + /**
  119 + * 获取文件的后缀名
  120 + *
  121 + * @param filePath 文件路径
  122 + * @param isContainSuffixSeparator 是否包含文件后缀分隔符
  123 + * @return java.lang.String
  124 + * @Author yangLang
  125 + * @Date 16:02 2020/9/2
  126 + */
  127 + public static String getFilePathExtension(String filePath, boolean isContainSuffixSeparator) {
  128 + Assert.notNull(filePath, "File is null");
  129 + int index = filePath.lastIndexOf(FILE_SUFFIX_SEPARATOR);
  130 + if (index == -1 || index >= filePath.length()) {
  131 + return null;
  132 + }
  133 + if (!isContainSuffixSeparator) {
  134 + index++;
  135 + }
  136 + return filePath.substring(index);
  137 + }
  138 +
  139 + /**
  140 + * 获取 MultipartFile 文件后缀
  141 + *
  142 + * @param file 文件
  143 + * @param isContainSuffixSeparator 是否包含文件后缀分隔符
  144 + * @return java.lang.String 后缀字符串
  145 + * @Author yangLang
  146 + * @Date 9:39 2020/9/3
  147 + */
  148 + public static String getMultipartFileExtension(MultipartFile file, boolean isContainSuffixSeparator) {
  149 + Assert.notNull(file, "File is null");
  150 + int index = file.getOriginalFilename().lastIndexOf(FILE_SUFFIX_SEPARATOR);
  151 + if (index == -1 || index >= file.getOriginalFilename().length()) {
  152 + return null;
  153 + }
  154 + if (!isContainSuffixSeparator) {
  155 + index++;
  156 + }
  157 + return file.getOriginalFilename().substring(index);
  158 + }
  159 +
  160 + /**
  161 + * 判断文件是否为期望的文件格式(不包含文件后缀分隔符)
  162 + *
  163 + * @param file 文件
  164 + * @param expectExtension 期望的文件格式
  165 + * @return boolean
  166 + * @Author yangLang
  167 + * @Date 16:17 2020/9/2
  168 + */
  169 + public static boolean judgeFileExtension(File file, String expectExtension) {
  170 + Assert.notNull(file, "Depend judge file is null");
  171 + Assert.notNull(expectExtension, "The expect extension is null");
  172 + String fileExtension = getFileExtension(file, false);
  173 + return expectExtension.equalsIgnoreCase(fileExtension);
  174 + }
  175 +
  176 + /**
  177 + * 判断文件路径是否为期望的文件格式(不包含文件后缀分隔符)
  178 + *
  179 + * @param filePath 文件路径
  180 + * @param expectExtension 期望的文件格式
  181 + * @return boolean
  182 + * @Author yangLang
  183 + * @Date 9:42 2020/9/3
  184 + */
  185 + public static boolean judgeFilePathExtension(String filePath, String expectExtension) {
  186 + Assert.notNull(filePath, "Depend judge file is null");
  187 + Assert.notNull(expectExtension, "The expect extension is null");
  188 + String fileExtension = getFilePathExtension(filePath, false);
  189 + return expectExtension.equalsIgnoreCase(fileExtension);
  190 + }
  191 +
  192 + /**
  193 + * 判断文件是否为期望的文件格式(不包含文件后缀分隔符)
  194 + *
  195 + * @param file 文件
  196 + * @param expectExtension 期望的格式
  197 + * @return boolean
  198 + * @Author yangLang
  199 + * @Date 16:19 2020/9/2
  200 + */
  201 + public static boolean judgeMultipartFileExtension(MultipartFile file, String expectExtension) {
  202 + Assert.notNull(file, "Depend judge file is null");
  203 + Assert.notNull(expectExtension, "The expect extension is null");
  204 + String fileExtension = getFilePathExtension(file.getOriginalFilename(), false);
  205 + return expectExtension.equalsIgnoreCase(fileExtension);
  206 + }
  207 +
  208 + /**
  209 + * multipartFile 转 File
  210 + *
  211 + * @param multipartFile 带转换的 multipartFile 文件
  212 + * @param parentFile 转换完成后的文件所在的目录
  213 + * @return java.io.File
  214 + * @Author yangLang
  215 + * @Date 17:03 2020/9/2
  216 + */
  217 + public static File multipartFile2File(MultipartFile multipartFile, File parentFile) {
  218 + Assert.notNull(multipartFile, "Depend trances file is null");
  219 + Assert.isTrue(parentFile.isDirectory(), "Parent File not a directory");
  220 + File tempFile = getFile(parentFile, multipartFile.getOriginalFilename());
  221 + try (InputStream inputStream = multipartFile.getInputStream()) {
  222 + FileUtils.copyInputStreamToFile(inputStream, tempFile);
  223 + } catch (IOException e) {
  224 + throw new ContextRuntimeException("文件转换失败");
  225 + }
  226 + return tempFile;
  227 + }
  228 +
  229 + /**
  230 + * 解压文件到指定目录,解压后的文件名和之前一致
  231 + *
  232 + * @param unZipFile 解压文件
  233 + * @param parentFile 解压文件后所置的目录
  234 + * @param encode 编码方式,默认是GBK
  235 + * @param isDeleteZipFile 是否需要删除压缩文件,默认不删除
  236 + * @return void
  237 + * @Author yangLang
  238 + * @Date 17:14 2020/9/2
  239 + */
  240 + public static void unZipFile(File unZipFile, File parentFile, String encode, Boolean isDeleteZipFile) {
  241 + Assert.notNull(parentFile, "Unzip file's parent file is null");
  242 + try (ZipFile zip = new ZipFile(unZipFile, Charset.forName(Optional.ofNullable(encode).orElse(DEFAULT_CHARSET)))) {
  243 + FileOutputStream out = null;
  244 + for (Enumeration<? extends ZipEntry> entries = zip.entries(); entries.hasMoreElements(); ) {
  245 + ZipEntry entry = entries.nextElement();
  246 + String zipEntryName = entry.getName();
  247 + try (InputStream in = zip.getInputStream(entry)) {
  248 + int index = zipEntryName.lastIndexOf(StringUtils.cleanPath(File.separator));
  249 + File file;
  250 + // 如果是文件夹,只创建文件夹,直接返回,无需读写文件
  251 + if (index == zipEntryName.length() - 1 || index == -1) {
  252 + getDirectoryFile(parentFile, zipEntryName);
  253 + continue;
  254 + } else {
  255 + // 获取文件的名称
  256 + String substring = zipEntryName.substring(0, index);
  257 + // 创建父文件目录
  258 + file = getDirectoryFile(parentFile, substring);
  259 + // 创建文件
  260 + file = getFile(file, zipEntryName.substring(index + 1));
  261 + }
  262 + out = new FileOutputStream(file);
  263 + byte[] buf1 = new byte[1024];
  264 + int len;
  265 + while ((len = in.read(buf1)) > 0) {
  266 + out.write(buf1, 0, len);
  267 + }
  268 + } finally {
  269 + if (out != null) {
  270 + out.flush();
  271 + out.close();
  272 + }
  273 + }
  274 + }
  275 + } catch (IOException e) {
  276 + throw new ContextRuntimeException("File = " + unZipFile.getName() + " unzip failed.");
  277 + }
  278 + if (Optional.ofNullable(isDeleteZipFile).orElse(Boolean.FALSE)) {
  279 + FileUtils.deleteQuietly(unZipFile);
  280 + }
  281 + }
  282 +
  283 + /**
  284 + * 压缩文件
  285 + *
  286 + * @param zipFiles 待压缩的文件
  287 + * @param parentFile 压缩完成的文件所在目录
  288 + * @param isDeleteSourcesFile 是否需要删除压缩前的源文件
  289 + * @param zipFileName 压缩完成后的文件名称
  290 + * @return java.io.File 压缩完成的文件
  291 + * @Author yangLang
  292 + * @Date 17:10 2020/9/2
  293 + */
  294 + public static File zipFile(List<File> zipFiles, File parentFile, String zipFileName, Boolean isDeleteSourcesFile) {
  295 + Assert.isTrue(ObjectUtils.nonEmpty(zipFiles), "Depending compress file is null");
  296 + Assert.notNull(zipFileName, "Compress file name is null");
  297 + Assert.notNull(parentFile, "Parent file of unzip file is null");
  298 + File newFile = getFile(parentFile, zipFileName);
  299 + Assert.notNull(newFile, "Zip file create failed");
  300 + try (FileOutputStream fos = new FileOutputStream(newFile);
  301 + ZipOutputStream zos = new ZipOutputStream(fos)) {
  302 + zipFiles.stream().forEach(item -> writeZip(item, "", zos));
  303 + } catch (IOException e) {
  304 + log.error("Failed to create compressed file:{}", e.getMessage());
  305 + }
  306 + if (Optional.ofNullable(isDeleteSourcesFile).orElse(Boolean.FALSE)) {
  307 + zipFiles.stream().forEach(item -> {
  308 + try {
  309 + FileUtils.deleteDirectory(item);
  310 + } catch (IOException e) {
  311 + log.error("File = {} delete failed", item.getAbsolutePath());
  312 + }
  313 + });
  314 + }
  315 + return newFile;
  316 + }
  317 +
  318 + /**
  319 + * 写压缩文件
  320 + *
  321 + * @param file 待压缩的文件夹
  322 + * @param parentPath 父文件路径
  323 + * @param zos 压缩流
  324 + * @return void
  325 + * @Author yangLang
  326 + * @Date 16:21 2020/8/6
  327 + */
  328 + private static void writeZip(File file, String parentPath, ZipOutputStream zos) {
  329 + if (!file.exists()) {
  330 + log.error("File = {} does not exist", file.getAbsolutePath());
  331 + return;
  332 + }
  333 + if (!file.isDirectory()) {
  334 + zipWrite2File(file, parentPath, zos);
  335 + return;
  336 + }
  337 + File[] subFiles = file.listFiles();
  338 + String subParentPath = parentPath + file.getName() + File.separator;
  339 + // 空目录则创建当前目录
  340 + if (subFiles.length == 0) {
  341 + try {
  342 + zos.putNextEntry(new ZipEntry(subParentPath));
  343 + } catch (IOException e) {
  344 + log.warn("{} Folder is empty", subParentPath);
  345 + }
  346 + return;
  347 + }
  348 + // 如果目录下包含文件,则递归压缩子文件
  349 + Arrays.stream(subFiles).forEach(item -> writeZip(item, subParentPath, zos));
  350 + }
  351 +
  352 + /**
  353 + * 压缩文件的时候写文件
  354 + *
  355 + * @param file 文件
  356 + * @param parentPath 父目录
  357 + * @param zos 压缩流
  358 + * @return void
  359 + * @Author yangLang
  360 + * @Date 16:29 2020/8/6
  361 + */
  362 + private static void zipWrite2File(File file, String parentPath, ZipOutputStream zos) {
  363 + ZipEntry ze = new ZipEntry(parentPath + file.getName());
  364 + try (FileInputStream fis = new FileInputStream(file)) {
  365 + zos.putNextEntry(ze);
  366 + byte[] content = new byte[1024];
  367 + int len;
  368 + while ((len = fis.read(content)) != -1) {
  369 + zos.write(content, 0, len);
  370 + zos.flush();
  371 + }
  372 + } catch (Exception e) {
  373 + log.error("Failed to compress file = {}:{}", file.getName(), e.getMessage());
  374 + }
  375 + }
  376 +}
... ...