| package com.xcong.excoin.common.utils; | 
|   | 
| import com.xcong.excoin.common.entity.FebsConstant; | 
| import com.google.common.base.Preconditions; | 
| import lombok.extern.slf4j.Slf4j; | 
| import org.apache.commons.lang3.ArrayUtils; | 
| import org.apache.commons.lang3.StringUtils; | 
|   | 
| import javax.servlet.http.HttpServletResponse; | 
| import java.io.*; | 
| import java.nio.file.Files; | 
| import java.nio.file.Paths; | 
| import java.util.Arrays; | 
| import java.util.zip.CRC32; | 
| import java.util.zip.CheckedOutputStream; | 
| import java.util.zip.ZipEntry; | 
| import java.util.zip.ZipOutputStream; | 
|   | 
| /** | 
|  * @author MrBird | 
|  */ | 
| @Slf4j | 
| public class FileUtil { | 
|   | 
|     private static final int BUFFER = 1024 * 8; | 
|   | 
|     /** | 
|      * 压缩文件或目录 | 
|      * | 
|      * @param fromPath 待压缩文件或路径 | 
|      * @param toPath   压缩文件,如 xx.zip | 
|      */ | 
|     public static void compress(String fromPath, String toPath) throws IOException { | 
|         File fromFile = new File(fromPath); | 
|         File toFile = new File(toPath); | 
|         if (!fromFile.exists()) { | 
|             throw new FileNotFoundException(fromPath + "不存在!"); | 
|         } | 
|         try ( | 
|                 FileOutputStream outputStream = new FileOutputStream(toFile); | 
|                 CheckedOutputStream checkedOutputStream = new CheckedOutputStream(outputStream, new CRC32()); | 
|                 ZipOutputStream zipOutputStream = new ZipOutputStream(checkedOutputStream) | 
|         ) { | 
|             String baseDir = ""; | 
|             compress(fromFile, zipOutputStream, baseDir); | 
|         } | 
|     } | 
|   | 
|     /** | 
|      * 文件下载 | 
|      * | 
|      * @param filePath 待下载文件路径 | 
|      * @param fileName 下载文件名称 | 
|      * @param delete   下载后是否删除源文件 | 
|      * @param response HttpServletResponse | 
|      * @throws Exception Exception | 
|      */ | 
|     public static void download(String filePath, String fileName, Boolean delete, HttpServletResponse response) throws Exception { | 
|         File file = new File(filePath); | 
|         if (!file.exists()) { | 
|             throw new Exception("文件未找到"); | 
|         } | 
|   | 
|         String fileType = getFileType(file); | 
|         if (!fileTypeIsValid(fileType)) { | 
|             throw new Exception("暂不支持该类型文件下载"); | 
|         } | 
|         response.setHeader("Content-Disposition", "attachment;fileName=" + java.net.URLEncoder.encode(fileName, "utf-8")); | 
|         response.setContentType("multipart/form-data"); | 
|         response.setCharacterEncoding("utf-8"); | 
|         try (InputStream inputStream = new FileInputStream(file); OutputStream os = response.getOutputStream()) { | 
|             byte[] b = new byte[2048]; | 
|             int length; | 
|             while ((length = inputStream.read(b)) > 0) { | 
|                 os.write(b, 0, length); | 
|             } | 
|         } finally { | 
|             if (delete) { | 
|                 delete(filePath); | 
|             } | 
|         } | 
|     } | 
|   | 
|     /** | 
|      * 递归删除文件或目录 | 
|      * | 
|      * @param filePath 文件或目录 | 
|      */ | 
|     public static void delete(String filePath) { | 
|         File file = new File(filePath); | 
|         if (file.isDirectory()) { | 
|             File[] files = file.listFiles(); | 
|             if (files != null) { | 
|                 Arrays.stream(files).forEach(f -> delete(f.getPath())); | 
|             } | 
|         } | 
|         try { | 
|             Files.delete(Paths.get(filePath)); | 
|         } catch (IOException e) { | 
|             log.error("删除失败", e); | 
|         } | 
|     } | 
|   | 
|     /** | 
|      * 获取文件类型 | 
|      * | 
|      * @param file 文件 | 
|      * @return 文件类型 | 
|      * @throws Exception Exception | 
|      */ | 
|     private static String getFileType(File file) throws Exception { | 
|         Preconditions.checkNotNull(file); | 
|         if (file.isDirectory()) { | 
|             throw new Exception("file不是文件"); | 
|         } | 
|         String fileName = file.getName(); | 
|         return fileName.substring(fileName.lastIndexOf(".") + 1); | 
|     } | 
|   | 
|   | 
|     /** | 
|      * 校验文件类型是否是允许下载的类型 | 
|      * (出于安全考虑:https://github.com/wuyouzhuguli/FEBS-Shiro/issues/40) | 
|      * | 
|      * @param fileType fileType | 
|      * @return Boolean | 
|      */ | 
|     private static Boolean fileTypeIsValid(String fileType) { | 
|         Preconditions.checkNotNull(fileType); | 
|         fileType = StringUtils.lowerCase(fileType); | 
|         return ArrayUtils.contains(FebsConstant.VALID_FILE_TYPE, fileType); | 
|     } | 
|   | 
|     private static void compress(File file, ZipOutputStream zipOut, String baseDir) throws IOException { | 
|         if (file.isDirectory()) { | 
|             compressDirectory(file, zipOut, baseDir); | 
|         } else { | 
|             compressFile(file, zipOut, baseDir); | 
|         } | 
|     } | 
|   | 
|     private static void compressDirectory(File dir, ZipOutputStream zipOut, String baseDir) throws IOException { | 
|         File[] files = dir.listFiles(); | 
|         if (files != null && ArrayUtils.isNotEmpty(files)) { | 
|             for (File file : files) { | 
|                 compress(file, zipOut, baseDir + dir.getName() + "/"); | 
|             } | 
|         } | 
|     } | 
|   | 
|     private static void compressFile(File file, ZipOutputStream zipOut, String baseDir) throws IOException { | 
|         if (!file.exists()) { | 
|             return; | 
|         } | 
|         try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file))) { | 
|             ZipEntry entry = new ZipEntry(baseDir + file.getName()); | 
|             zipOut.putNextEntry(entry); | 
|             int count; | 
|             byte[] data = new byte[BUFFER]; | 
|             while ((count = bis.read(data, 0, BUFFER)) != -1) { | 
|                 zipOut.write(data, 0, count); | 
|             } | 
|         } | 
|     } | 
| } |