content: package org.superboot.utils;
  
  import org.springframework.web.multipart.MultipartFile;
  import org.springframework.web.multipart.MultipartHttpServletRequest;
  
  import javax.servlet.http.HttpServletRequest;
  import javax.servlet.http.HttpServletResponse;
  import java.io.*;
  import java.math.BigInteger;
  import java.security.MessageDigest;
  import java.util.*;
  import java.util.zip.ZipEntry;
  import java.util.zip.ZipFile;
  import java.util.zip.ZipOutputStream;
  
  /**
   * <b> 文件操作类 </b>
   * <p>
   * 功能描述:提供对文件的读写、文件夹访问操作
   * </p>
   */
  public class FileUtils {
  
      /**
       * 读取文件
       *
       * @param path 文件路径
       * @return
       * @throws IOException
       */
      public static byte[] read(String path)
              throws IOException {
          int base_size = 1024;
          File file = new File(path);
  
          if (!(file.exists())) {
              return null;
          }
  
          FileInputStream fis = new FileInputStream(file);
          int len = 0;
          byte[] dataByte = new byte[base_size];
  
          ByteArrayOutputStream out = new ByteArrayOutputStream(base_size);
          while ((len = fis.read(dataByte)) != -1) {
              out.write(dataByte, 0, len);
          }
          byte[] content = out.toByteArray();
  
          fis.close();
          out.close();
  
          if (content.length == 0) {
              return null;
          }
  
          return content;
      }
  
      /**
       * 写文件
       *
       * @param path 路径
       * @param data 文件数据
       * @throws IOException
       */
      public static void write(String path, byte[] data)
              throws IOException {
          File file = new File(path);
  
          if (!(file.exists())) {
              file.createNewFile();
          }
  
          FileOutputStream fos = new FileOutputStream(file);
          fos.write(data);
          fos.flush();
          fos.close();
      }
  
      /**
       * 获取文件列表
       *
       * @param baseDirName 文件夹名称
       * @return
       */
      public static List<String> findFiles(String baseDirName) {
          List files = new ArrayList();
  
          File baseDir = new File(baseDirName);
          if ((!(baseDir.exists())) || (!(baseDir.isDirectory()))) {
              System.err.println("search error：" + baseDirName + "is not a dir！");
          } else {
              String[] filelist = baseDir.list();
              for (String fileName : filelist) {
                  files.add(fileName);
              }
          }
          return files;
      }
  
      /**
       * 读取文件夹文件列表
       *
       * @param baseDirName 文件夹名称
       * @param fileFilter  过滤器
       * @return
       */
      public static List<String> findFileNames(String baseDirName, FileFilter fileFilter) {
          List files = new ArrayList();
  
          File baseDir = new File(baseDirName);
          if ((!(baseDir.exists())) || (!(baseDir.isDirectory()))) {
              System.err.println("search error：" + baseDirName + "is not a dir！");
          } else {
              File[] filelist = baseDir.listFiles(fileFilter);
              for (File file : filelist) {
                  if (file.isFile()) {
                      files.add(file.getName());
  
                  }
              }
          }
          return files;
      }
  
      /**
       * 获取文件的MD5
       *
       * @param fileName 文件完整路径+名称
       * @return
       */
      public static String getFileMD5(String fileName) {
          File file = new File(fileName);
          if (!file.isFile()) {
              return null;
          }
          MessageDigest digest = null;
          FileInputStream in = null;
          byte buffer[] = new byte[8192];
          int len;
          try {
              digest = MessageDigest.getInstance("MD5");
              in = new FileInputStream(file);
              while ((len = in.read(buffer)) != -1) {
                  digest.update(buffer, 0, len);
              }
              BigInteger bigInt = new BigInteger(1, digest.digest());
              return bigInt.toString(16);
          } catch (Exception e) {
              e.printStackTrace();
              return null;
          } finally {
              try {
                  in.close();
              } catch (Exception e) {
                  e.printStackTrace();
              }
          }
      }
  
      /**
       * 获取文件的SHA-1码 一般效率低于MD5
       *
       * @param fileName
       * @return
       */
      public static String getFileSha1(String fileName) {
          File file = new File(fileName);
          if (!file.isFile()) {
              return null;
          }
          MessageDigest digest = null;
          FileInputStream in = null;
          byte buffer[] = new byte[8192];
          int len;
          try {
              digest = MessageDigest.getInstance("SHA-1");
              in = new FileInputStream(file);
              while ((len = in.read(buffer)) != -1) {
                  digest.update(buffer, 0, len);
              }
              BigInteger bigInt = new BigInteger(1, digest.digest());
              return bigInt.toString(16);
          } catch (Exception e) {
              e.printStackTrace();
              return null;
          } finally {
              try {
                  in.close();
              } catch (Exception e) {
                  e.printStackTrace();
              }
          }
      }
  
      /**
       * 复制单个文件，如果目标文件存在，则不覆盖
       *
       * @param srcFileName  待复制的文件名
       * @param descFileName 目标文件名
       * @return 如果复制成功，则返回true，否则返回false
       */
      public static boolean copyFile(String srcFileName, String descFileName) {
          return FileUtils.copyFileCover(srcFileName, descFileName, false);
      }
  
  
      /**
       * 复制单个文件
       *
       * @param srcFileName  待复制的文件名
       * @param descFileName 目标文件名
       * @param coverlay     如果目标文件已存在，是否覆盖
       * @return 如果复制成功，则返回true，否则返回false
       */
      public static boolean copyFileCover(String srcFileName,
                                          String descFileName, boolean coverlay) {
          File srcFile = new File(srcFileName);
          // 判断源文件是否存在
          if (!srcFile.exists()) {
              return false;
          }
          // 判断源文件是否是合法的文件
          else if (!srcFile.isFile()) {
              return false;
          }
          File descFile = new File(descFileName);
          // 判断目标文件是否存在
          if (descFile.exists()) {
              // 如果目标文件存在，并且允许覆盖
              if (coverlay) {
                  if (!FileUtils.delFile(descFileName)) {
                      return false;
                  }
              } else {
                  return false;
              }
          } else {
              if (!descFile.getParentFile().exists()) {
                  // 如果目标文件所在的目录不存在，则创建目录
                  // 创建目标文件所在的目录
                  if (!descFile.getParentFile().mkdirs()) {
                      return false;
                  }
              }
          }
  
          // 准备复制文件
          // 读取的位数
          int readByte = 0;
          InputStream ins = null;
          OutputStream outs = null;
          try {
              // 打开源文件
              ins = new FileInputStream(srcFile);
              // 打开目标文件的输出流
              outs = new FileOutputStream(descFile);
              byte[] buf = new byte[1024];
              // 一次读取1024个字节，当readByte为-1时表示文件已经读取完毕
              while ((readByte = ins.read(buf)) != -1) {
                  // 将读取的字节流写入到输出流
                  outs.write(buf, 0, readByte);
              }
              return true;
          } catch (Exception e) {
              return false;
          } finally {
              // 关闭输入输出流，首先关闭输出流，然后再关闭输入流
              if (outs != null) {
                  try {
                      outs.close();
                  } catch (IOException oute) {
                      oute.printStackTrace();
                  }
              }
              if (ins != null) {
                  try {
                      ins.close();
                  } catch (IOException ine) {
                      ine.printStackTrace();
                  }
              }
          }
      }
  
      /**
       * 复制整个目录的内容，如果目标目录存在，则不覆盖
       *
       * @param srcDirName  源目录名
       * @param descDirName 目标目录名
       * @return 如果复制成功返回true，否则返回false
       */
      public static boolean copyDirectory(String srcDirName, String descDirName) {
          return FileUtils.copyDirectoryCover(srcDirName, descDirName,
                  false);
      }
  
      /**
       * 复制整个目录的内容
       *
       * @param srcDirName  源目录名
       * @param descDirName 目标目录名
       * @param coverlay    如果目标目录存在，是否覆盖
       * @return 如果复制成功返回true，否则返回false
       */
      public static boolean copyDirectoryCover(String srcDirName,
                                               String descDirName, boolean coverlay) {
          File srcDir = new File(srcDirName);
          // 判断源目录是否存在
          if (!srcDir.exists()) {
              return false;
          }
          // 判断源目录是否是目录
          else if (!srcDir.isDirectory()) {
              return false;
          }
          // 如果目标文件夹名不以文件分隔符结尾，自动添加文件分隔符
          String descDirNames = descDirName;
          if (!descDirNames.endsWith(File.separator)) {
              descDirNames = descDirNames + File.separator;
          }
          File descDir = new File(descDirNames);
          // 如果目标文件夹存在
          if (descDir.exists()) {
              if (coverlay) {
                  // 允许覆盖目标目录
                  if (!FileUtils.delFile(descDirNames)) {
                      return false;
                  }
              } else {
                  return false;
              }
          } else {
              // 创建目标目录
              if (!descDir.mkdirs()) {
                  return false;
              }
  
          }
  
          boolean flag = true;
          // 列出源目录下的所有文件名和子目录名
          File[] files = srcDir.listFiles();
          for (int i = 0; i < files.length; i++) {
              // 如果是一个单个文件，则直接复制
              if (files[i].isFile()) {
                  flag = FileUtils.copyFile(files[i].getAbsolutePath(),
                          descDirName + files[i].getName());
                  // 如果拷贝文件失败，则退出循环
                  if (!flag) {
                      break;
                  }
              }
              // 如果是子目录，则继续复制目录
              if (files[i].isDirectory()) {
                  flag = FileUtils.copyDirectory(files[i]
                          .getAbsolutePath(), descDirName + files[i].getName());
                  // 如果拷贝目录失败，则退出循环
                  if (!flag) {
                      break;
                  }
              }
          }
  
          if (!flag) {
              return false;
          }
          return true;
  
      }
  
      /**
       * 删除文件，可以删除单个文件或文件夹
       *
       * @param fileName 被删除的文件名
       * @return 如果删除成功，则返回true，否是返回false
       */
      public static boolean delFile(String fileName) {
          File file = new File(fileName);
          if (!file.exists()) {
              return true;
          } else {
              if (file.isFile()) {
                  return FileUtils.deleteFile(fileName);
              } else {
                  return FileUtils.deleteDirectory(fileName);
              }
          }
      }
  
      /**
       * 删除单个文件
       *
       * @param fileName 被删除的文件名
       * @return 如果删除成功，则返回true，否则返回false
       */
      public static boolean deleteFile(String fileName) {
          File file = new File(fileName);
          if (file.exists() && file.isFile()) {
              if (file.delete()) {
                  return true;
              } else {
                  return false;
              }
          } else {
              return true;
          }
      }
  
      /**
       * 删除目录及目录下的文件
       *
       * @param dirName 被删除的目录所在的文件路径
       * @return 如果目录删除成功，则返回true，否则返回false
       */
      public static boolean deleteDirectory(String dirName) {
          String dirNames = dirName;
          if (!dirNames.endsWith(File.separator)) {
              dirNames = dirNames + File.separator;
          }
          File dirFile = new File(dirNames);
          if (!dirFile.exists() || !dirFile.isDirectory()) {
              return true;
          }
          boolean flag = true;
          // 列出全部文件及子目录
          File[] files = dirFile.listFiles();
          for (int i = 0; i < files.length; i++) {
              // 删除子文件
              if (files[i].isFile()) {
                  flag = FileUtils.deleteFile(files[i].getAbsolutePath());
                  // 如果删除文件失败，则退出循环
                  if (!flag) {
                      break;
                  }
              }
              // 删除子目录
              else if (files[i].isDirectory()) {
                  flag = FileUtils.deleteDirectory(files[i]
                          .getAbsolutePath());
                  // 如果删除子目录失败，则退出循环
                  if (!flag) {
                      break;
                  }
              }
          }
  
          if (!flag) {
              return false;
          }
          // 删除当前目录
          if (dirFile.delete()) {
              return true;
          } else {
              return false;
          }
  
      }
  
      /**
       * 创建单个文件
       *
       * @param descFileName 文件名，包含路径
       * @return 如果创建成功，则返回true，否则返回false
       */
      public static boolean createFile(String descFileName) {
          File file = new File(descFileName);
          if (file.exists()) {
              return false;
          }
          if (descFileName.endsWith(File.separator)) {
              return false;
          }
          if (!file.getParentFile().exists()) {
              // 如果文件所在的目录不存在，则创建目录
              if (!file.getParentFile().mkdirs()) {
                  return false;
              }
          }
  
          // 创建文件
          try {
              if (file.createNewFile()) {
                  return true;
              } else {
                  return false;
              }
          } catch (Exception e) {
              e.printStackTrace();
              return false;
          }
  
      }
  
      /**
       * 创建目录
       *
       * @param descDirName 目录名,包含路径
       * @return 如果创建成功，则返回true，否则返回false
       */
      public static boolean createDirectory(String descDirName) {
          String descDirNames = descDirName;
          if (!descDirNames.endsWith(File.separator)) {
              descDirNames = descDirNames + File.separator;
          }
          File descDir = new File(descDirNames);
          if (descDir.exists()) {
              return false;
          }
          // 创建目录
          if (descDir.mkdirs()) {
              return true;
          } else {
              return false;
          }
  
      }
  
      /**
       * 压缩文件或目录
       *
       * @param srcDirName   压缩的根目录
       * @param fileName     根目录下的待压缩的文件名或文件夹名，其中*或""表示跟目录下的全部文件
       * @param descFileName 目标zip文件
       */
      public static void zipFiles(String srcDirName, String fileName,
                                  String descFileName) {
          // 判断目录是否存在
          if (srcDirName == null) {
              return;
          }
          File fileDir = new File(srcDirName);
          if (!fileDir.exists() || !fileDir.isDirectory()) {
              return;
          }
          String dirPath = fileDir.getAbsolutePath();
          File descFile = new File(descFileName);
          try {
              ZipOutputStream zouts = new ZipOutputStream(new FileOutputStream(
                      descFile));
              if ("*".equals(fileName) || "".equals(fileName)) {
                  FileUtils.zipDirectoryToZipFile(dirPath, fileDir, zouts);
              } else {
                  File file = new File(fileDir, fileName);
                  if (file.isFile()) {
                      FileUtils.zipFilesToZipFile(dirPath, file, zouts);
                  } else {
                      FileUtils
                              .zipDirectoryToZipFile(dirPath, file, zouts);
                  }
              }
              zouts.close();
          } catch (Exception e) {
              e.printStackTrace();
          }
  
      }
  
      /**
       * 解压缩ZIP文件，将ZIP文件里的内容解压到descFileName目录下
       *
       * @param zipFileName  需要解压的ZIP文件
       * @param descFileName 目标文件
       */
      public static boolean unZipFiles(String zipFileName, String descFileName) {
          String descFileNames = descFileName;
          if (!descFileNames.endsWith(File.separator)) {
              descFileNames = descFileNames + File.separator;
          }
          try {
              // 根据ZIP文件创建ZipFile对象
              ZipFile zipFile = new ZipFile(zipFileName);
              ZipEntry entry = null;
              String entryName = null;
              String descFileDir = null;
              byte[] buf = new byte[4096];
              int readByte = 0;
              // 获取ZIP文件里所有的entry
              @SuppressWarnings("rawtypes")
              Enumeration enums = zipFile.entries();
              // 遍历所有entry
              while (enums.hasMoreElements()) {
                  entry = (ZipEntry) enums.nextElement();
                  // 获得entry的名字
                  entryName = entry.getName();
                  descFileDir = descFileNames + entryName;
                  if (entry.isDirectory()) {
                      // 如果entry是一个目录，则创建目录
                      new File(descFileDir).mkdirs();
                      continue;
                  } else {
                      // 如果entry是一个文件，则创建父目录
                      new File(descFileDir).getParentFile().mkdirs();
                  }
                  File file = new File(descFileDir);
                  // 打开文件输出流
                  OutputStream os = new FileOutputStream(file);
                  // 从ZipFile对象中打开entry的输入流
                  InputStream is = zipFile.getInputStream(entry);
                  while ((readByte = is.read(buf)) != -1) {
                      os.write(buf, 0, readByte);
                  }
                  os.close();
                  is.close();
              }
              zipFile.close();
              return true;
          } catch (Exception e) {
              return false;
          }
      }
  
      /**
       * 将目录压缩到ZIP输出流
       *
       * @param dirPath 目录路径
       * @param fileDir 文件信息
       * @param zouts   输出流
       */
      public static void zipDirectoryToZipFile(String dirPath, File fileDir,
                                               ZipOutputStream zouts) {
          if (fileDir.isDirectory()) {
              File[] files = fileDir.listFiles();
              // 空的文件夹
              if (files.length == 0) {
                  // 目录信息
                  ZipEntry entry = new ZipEntry(getEntryName(dirPath, fileDir));
                  try {
                      zouts.putNextEntry(entry);
                      zouts.closeEntry();
                  } catch (Exception e) {
                      e.printStackTrace();
                  }
                  return;
              }
  
              for (int i = 0; i < files.length; i++) {
                  if (files[i].isFile()) {
                      // 如果是文件，则调用文件压缩方法
                      FileUtils
                              .zipFilesToZipFile(dirPath, files[i], zouts);
                  } else {
                      // 如果是目录，则递归调用
                      FileUtils.zipDirectoryToZipFile(dirPath, files[i],
                              zouts);
                  }
              }
  
          }
  
      }
  
      /**
       * 将文件压缩到ZIP输出流
       *
       * @param dirPath 目录路径
       * @param file    文件
       * @param zouts   输出流
       */
      public static void zipFilesToZipFile(String dirPath, File file,
                                           ZipOutputStream zouts) {
          FileInputStream fin = null;
          ZipEntry entry = null;
          // 创建复制缓冲区
          byte[] buf = new byte[4096];
          int readByte = 0;
          if (file.isFile()) {
              try {
                  // 创建一个文件输入流
                  fin = new FileInputStream(file);
                  // 创建一个ZipEntry
                  entry = new ZipEntry(getEntryName(dirPath, file));
                  // 存储信息到压缩文件
                  zouts.putNextEntry(entry);
                  // 复制字节到压缩文件
                  while ((readByte = fin.read(buf)) != -1) {
                      zouts.write(buf, 0, readByte);
                  }
                  zouts.closeEntry();
                  fin.close();
                  System.out
                          .println("添加文件 " + file.getAbsolutePath() + " 到zip文件中!");
              } catch (Exception e) {
                  e.printStackTrace();
              }
          }
  
      }
  
      /**
       * 获取待压缩文件在ZIP文件中entry的名字，即相对于跟目录的相对路径名
       *
       * @param dirPath 目录名
       * @param file    entry文件名
       * @return
       */
      private static String getEntryName(String dirPath, File file) {
          String dirPaths = dirPath;
          if (!dirPaths.endsWith(File.separator)) {
              dirPaths = dirPaths + File.separator;
          }
          String filePath = file.getAbsolutePath();
          // 对于目录，必须在entry名字后面加上"/"，表示它将以目录项存储
          if (file.isDirectory()) {
              filePath += "/";
          }
          int index = filePath.indexOf(dirPaths);
  
          return filePath.substring(index + dirPaths.length());
      }
  
  
      /**
       * 将内容写入文件
       *
       * @param content
       * @param filePath
       */
      public static void writeFile(String content, String filePath) {
          try {
              if (FileUtils.createFile(filePath)) {
                  FileWriter fileWriter = new FileWriter(filePath, true);
                  BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
                  bufferedWriter.write(content);
                  bufferedWriter.close();
                  fileWriter.close();
              }
          } catch (Exception e) {
              e.printStackTrace();
          }
      }
  
      /**
       * 下载
       *
       * @param filePath 文件路径
       * @param fileName 下载的文件名
       * @throws Exception
       */
      public static HttpServletResponse downloadFile(HttpServletResponse response,
                                                     String filePath, String fileName) throws Exception {
          File file = new File(filePath);
          response.setContentType("application/x-download");
          response.setHeader("Pragma", "public");
          response.setHeader("Cache-Control",
                  "must-revalidate, post-check=0, pre-check=0");
          OutputStream out = null;
          InputStream in = null;
          fileName = new String(fileName.getBytes("GBK"), "ISO-8859-1");
          response.addHeader("Content-disposition", "attachment;filename="
                  + fileName);// 设定输出文件头
  
          try {
              out = response.getOutputStream();
              in = new FileInputStream(file);
              int len = in.available();
              byte[] b = new byte[len];
              in.read(b);
              out.write(b);
              out.flush();
  
          } catch (Exception e) {
              throw new Exception("下载失败!");
          } finally {
              if (in != null) {
                  in.close();
              }
              if (out != null) {
                  out.close();
              }
          }
          return response;
      }
  
      /**
       * 下载(流的方式)
       *
       * @param response
       * @param is       输入流
       * @param realName 下载的文件名字
       */
      public static void downloadFile(HttpServletResponse response, InputStream is, String realName) {
          BufferedInputStream bis = null;
          BufferedOutputStream bos = null;
          try {
              response.setContentType("text/html;charset=UTF-8");
              //request.setCharacterEncoding("UTF-8");
              long fileLength = is.available();
  
              response.setContentType("application/octet-stream");
              realName = new String(realName.getBytes("GBK"), "ISO8859-1");
              response.setHeader("Content-disposition", "attachment; filename="
                      + realName);
              response.setHeader("Content-Length", String.valueOf(fileLength));
              bis = new BufferedInputStream(is);
              bos = new BufferedOutputStream(response.getOutputStream());
              byte[] buff = new byte[2048];
              int bytesRead;
              while (-1 != (bytesRead = bis.read(buff, 0, buff.length))) {
                  bos.write(buff, 0, bytesRead);
              }
          } catch (Exception e) {
              // e.printStackTrace();//如果取消下载，这里会捕捉到异常
          } finally {
              try {
                  bos.close();
                  bis.close();
              } catch (IOException e) {
                  e.printStackTrace();
              }
          }
      }
  
      /**
       * 上传返回输入流
       *
       * @param request
       * @return
       */
      public static InputStream uploadFile(HttpServletRequest request) {
          InputStream is = null;
          MultipartHttpServletRequest mRequest = (MultipartHttpServletRequest) request;
          Map<String, MultipartFile> fileMap = mRequest.getFileMap();
          Iterator<Map.Entry<String, MultipartFile>> it = fileMap.entrySet().iterator();
          if (it.hasNext()) {//存在上传文件，进行处理
              Map.Entry<String, MultipartFile> entry = it.next();
              MultipartFile mFile = entry.getValue();
              try {
                  is = mFile.getInputStream();
              } catch (IOException e) {
                  e.printStackTrace();
              }
          }
          return is;
      }
  
  
  }
  