package com.zzg.common.utils; import com.zzg.common.utils.enums.FileHeadEnum; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import org.springframework.http.MediaType; import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletResponse; import java.io.*; import java.net.URLEncoder; import java.util.Base64; import java.util.List; import java.util.stream.Collectors; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; /** * Description: 文件处理工具类 * * @author wangjiang * @date 2018/11/12 */ public class FileUtil { private FileUtil() { throw new IllegalStateException("Utility class"); } private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(FileUtil.class); /** * 后缀名与文件名的分隔符 */ public static final String FILE_PUF = "."; public static final long KB = 1024L; /** * 文件大小单位转换 * * @param size * @return */ public static String getSize(long size) { if (size >= KB * KB * KB) { return size / KB * KB * KB + " GB"; } else if (size >= KB * KB) { return size / KB * KB + " MB"; } else if (size >= KB) { return size / KB + " KB"; } else { return size + " B"; } } /** * 将 MultipartFile 转换为 File * * @param multipartFile 要转换的 MultipartFile 对象 * @return 转换后的 File 对象 * @throws IOException 如果文件处理过程中出现错误 */ public static File convertToFile(MultipartFile multipartFile) throws IOException { // 创建临时文件 File file = File.createTempFile("temp", multipartFile.getOriginalFilename()); try (FileOutputStream fos = new FileOutputStream(file)) { // 将 MultipartFile 的内容写入到 File 中 fos.write(multipartFile.getBytes()); } // 返回 File 对象 return file; } /** * 获取文件后缀名 * * @param fileName * @return */ public static String getSuffix(String fileName) { return fileName.substring(fileName.lastIndexOf(FILE_PUF) + 1); } /** * 去掉文件后缀名 * * @param fileName * @return */ public static String removeSuffix(String fileName) { return fileName.substring(0, fileName.lastIndexOf(FILE_PUF)); } /** * 保存文件 * * @param inputStream 输入流 * @param pathName 要保存的文件名 * @see #saveFile(InputStream, File) */ public static void saveFile(InputStream inputStream, String pathName) { saveFile(inputStream, new File(pathName)); } /** * 保存文件 * * @param inputStream 输入流 * @param file 要保存的文件 */ public static void saveFile(InputStream inputStream, File file) { try { FileUtils.copyInputStreamToFile(inputStream, file); } catch (IOException e) { log.error("保存文件失败", e); throw new RuntimeException("文件保存失败"); } } /** * @param file 要输出的文件 * @param fileName 下载时的文件名 * @see #outFile(InputStream, String, String) */ public static void outFile(File file, String fileName) { try (InputStream inputStream = FileUtils.openInputStream(file)) { outFile(inputStream, fileName, String.valueOf(file.length())); } catch (IOException e) { throw new RuntimeException("打开服务器文件失败" + e.getMessage(), e); } } /** * 实现文件下载 * * @param input 输入流 * @param fileName 文件名 * @see #setOutFileHeader(HttpServletResponse, String, String) */ public static void outFile(InputStream input, String fileName, String length) throws IOException { try { HttpServletResponse response = ContextUtil.getServletResponse(); setOutFileHeader(response, fileName, length); OutputStream output = response.getOutputStream(); IOUtils.copyLarge(input, output); output.close(); input.close(); } catch (IOException e) { throw new RuntimeException("文件输出失败", e); } } /** * 拷贝文件到指定目录 * * @param fileNames * @param destDir * @throws IOException */ public static void synFiles(List fileNames, String destDir) throws IOException { List files = fileNames.stream().map(File::new).collect(Collectors.toList()); File destFile = new File(destDir); if (!destFile.exists()) { boolean bool = destFile.mkdirs(); if (!destFile.isDirectory() || !bool) { throw new IllegalAccessError("目录:" + destDir + "创建失败"); } } FileUtils.copyToDirectory(files, destFile); } /** * @param response 响应请求 * @param fileName 下载的文件名字 * @param length 下载文件的长度 */ public static void setOutFileHeader(HttpServletResponse response, String fileName, String length) { response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE); try { String encode = URLEncoder.encode(fileName, "UTF-8"); response.addHeader("Content-Disposition", "attachment; filename=\"" + encode + "\""); } catch (UnsupportedEncodingException e) { throw new RuntimeException("设置下载文件响应头失败!", e); } if (StringUtils.isNotBlank(length)) { response.addHeader("Content-Length", length); } } /** * @see #copyZipOut(ZipOutputStream, InputStream, ZipEntry) */ public static void copyZipOut(ZipOutputStream outputStream, File... files) { for (File file : files) { try (InputStream inputStream = FileUtils.openInputStream(file)) { copyZipOut(outputStream, inputStream, new ZipEntry(file.getName())); } catch (IOException e) { throw new RuntimeException("打开服务器文件失败" + e.getMessage(), e); } } } /** * 将一个输入流数据 输出到压缩包里 * * @param outputStream 输出流 * @param inputStream 输入流 * @param zipEntry 压缩对象 */ public static void copyZipOut(ZipOutputStream outputStream, InputStream inputStream, ZipEntry zipEntry) { try { outputStream.putNextEntry(zipEntry); IOUtils.copyLarge(inputStream, outputStream); outputStream.closeEntry(); } catch (IOException e) { throw new RuntimeException("zip压缩输出文件:" + zipEntry.getName() + "时失败", e); } } /** * @param folder 文件夹 * @param response */ public static void copyZipOut(String folder, HttpServletResponse response) { ZipOutputStream out = null; BufferedOutputStream bos = null; try { File sourceFile = new File(folder); //将zip以流的形式输出到前台 response.setHeader("content-type", "application/octet-stream"); // long size = FileUtils.sizeOf(sourceFile); // response.setHeader("Content-Length", String.valueOf(size)); // 设置浏览器响应头对应的Content-disposition response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode("档案管理.zip", "UTF-8")); response.setCharacterEncoding("utf-8"); //创建zip输出流 out = new ZipOutputStream(response.getOutputStream()); //创建缓冲输出流 bos = new BufferedOutputStream(out); //调用压缩函数 compress(out, bos, sourceFile, sourceFile.getName()); out.flush(); } catch (Exception e) { e.printStackTrace(); } finally { IOCloseUtil.close(bos, out); } } /** * 文件压缩 * * @param out * @param bos * @param sourceFile * @param base */ public static void compress(ZipOutputStream out, BufferedOutputStream bos, File sourceFile, String base) { FileInputStream fos = null; BufferedInputStream bis = null; try { //如果路径为目录(文件夹) if (sourceFile.isDirectory()) { //取出文件夹中的文件(或子文件夹) File[] flist = sourceFile.listFiles(); if (flist.length == 0) {//如果文件夹为空,则只需在目的地zip文件中写入一个目录进入点 out.putNextEntry(new ZipEntry(base + "/")); } else {//如果文件夹不为空,则递归调用compress,文件夹中的每一个文件(或文件夹)进行压缩 for (int i = 0; i < flist.length; i++) { compress(out, bos, flist[i], base + "/" + flist[i].getName()); } } } else {//如果不是目录(文件夹),即为文件,则先写入目录进入点,之后将文件写入zip文件中 out.putNextEntry(new ZipEntry(base)); fos = new FileInputStream(sourceFile); bis = new BufferedInputStream(fos); int tag; //将源文件写入到zip文件中 while ((tag = bis.read()) != -1) { out.write(tag); } bis.close(); fos.close(); } } catch (Exception e) { e.printStackTrace(); } finally { IOCloseUtil.close(bis, fos); } } /** * @param file 要输出的文件 * @param fileName 下载时的文件名 * @param token 要传输的token * @see #outFileAndToken(InputStream, String, String, String) */ public static void outFileAndToken(File file, String fileName, String token) { try (InputStream inputStream = FileUtils.openInputStream(file)) { outFileAndToken(inputStream, fileName, String.valueOf(file.length()), token); } catch (IOException e) { throw new RuntimeException("打开服务器文件失败" + e.getMessage(), e); } } /** * 实现文件下载 * * @param input 输入流 * @param fileName 文件名 * @param token 要传输的token * @see #setOutFileHeader(HttpServletResponse, String, String) */ public static void outFileAndToken(InputStream input, String fileName, String length, String token) { try { HttpServletResponse response = ContextUtil.getServletResponse(); response.addHeader("token", token); setOutFileHeader(response, fileName, length); OutputStream output = response.getOutputStream(); IOUtils.copyLarge(input, output); } catch (IOException e) { throw new RuntimeException("文件输出失败", e); } } /** * 输出图片 */ public static void outImg(HttpServletResponse response, String path) { FileInputStream fis = null; response.setContentType("image/gif"); try { OutputStream out = response.getOutputStream(); File file = new File(path); fis = new FileInputStream(file); byte[] b = new byte[fis.available()]; fis.read(b); out.write(b); out.flush(); } catch (Exception e) { e.printStackTrace(); } finally { if (fis != null) { try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } } } /** * 输出图片 */ public static void outArcgisNode(HttpServletResponse response, String path) { FileInputStream fis = null; try { OutputStream out = response.getOutputStream(); File file = new File(path); fis = new FileInputStream(file); byte[] b = new byte[fis.available()]; fis.read(b); out.write(b); out.flush(); } catch (Exception e) { log.error("outArcgisNode error: {}", e.getMessage()); } finally { if (fis != null) { try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } } } /** * 图片转base64 */ public static String transformPictureToBase64Data(String LoadPath, String DataName, String fileType) { Base64.Encoder encoder = Base64.getEncoder(); //获取Base64编码器 byte[] ImgContainer; //数据集缓存器 FileInputStream fileInputStream = null; //文件输入流 try { fileInputStream = new FileInputStream(LoadPath + DataName); //到指定路径寻找文件 ImgContainer = new byte[fileInputStream.available()]; //设置图片字节数据缓冲区大小 fileInputStream.read(ImgContainer); //将数据流中的图片数据读进缓冲区 String Base64ImgData = String.format("data:image/%s;base64,%s", fileType, encoder.encodeToString(ImgContainer)); //将图片编码转换成Base64格式的数据集 fileInputStream.close(); //关闭数据流 return Base64ImgData; //将缓冲区数据转换成字符数据返回 } catch (FileNotFoundException e) { return "找不到指定文件!"; } catch (IOException e) { e.printStackTrace(); } return "null"; } /** * 获取文件的原始头信息 * 判断文件后缀 * * @param fis * @return true:格式无异常 false:格式异常 */ public static boolean CheckFileHead(FileInputStream fis) { StringBuilder stringBuilder = new StringBuilder(); try { //大小不同,获取的文件头长度也不一样 byte[] b = new byte[4]; fis.read(b, 0, b.length); if (b == null || b.length <= 0) { return false; } for (int i = 0; i < b.length; i++) { // 以十六进制(基数 16)无符号整数形式返回一个整数参数的字符串表示形式 int v = b[i] & 0xFF; String hv = Integer.toHexString(v); if (hv.length() < 2) { stringBuilder.append(0); } stringBuilder.append(hv); } } catch (Exception e) { e.printStackTrace(); } String head = stringBuilder.toString(); String code = FileHeadEnum.getSuffixByCode(head); return org.apache.commons.lang3.StringUtils.isNotEmpty(code); } /** * 获取下载路径 * * @param uploadDir 文件夹 * @param fileName 文件名称 */ public static final File getAbsoluteFile(String uploadDir, String fileName) throws IOException { File desc = new File(uploadDir + File.separator + fileName); if (!desc.getParentFile().exists()) { desc.getParentFile().mkdirs(); } if (!desc.exists()) { desc.createNewFile(); } return desc; } /** * 复制文件 * * @param sourcePath 源文件绝对路径 * @param targetPath 目标文件绝对路径 * @throws Exception 异常 */ public static void copy(String sourcePath, String targetPath) throws Exception { //字节输入流,用来读取文件 FileInputStream in = new FileInputStream(new File(sourcePath)); //字节输出流,用来写文件 FileOutputStream out = new FileOutputStream(new File(targetPath)); byte[] buff = new byte[512]; int n = 0; while ((n = in.read(buff)) != -1) { out.write(buff, 0, n); } out.flush(); in.close(); out.close(); System.out.println("复制完成"); } /** * 根据路径删除指定的目录或文件,无论存在与否 * * @param sPath 要删除的目录或文件 * @return 删除成功返回 true,否则返回 false。 */ public static boolean deleteFolder(String sPath) { boolean flag = false; File file = new File(sPath); // 判断目录或文件是否存在 if (!file.exists()) { // 不存在返回 false return flag; } else { // 判断是否为文件 if (file.isFile()) { // 为文件时调用删除文件方法 return deleteFile(sPath); } else { // 为目录时调用删除目录方法 return deleteDirectory(sPath); } } } /** * 删除单个文件 * * @param sPath 被删除文件的文件名 * @return 单个文件删除成功返回true,否则返回false */ public static boolean deleteFile(String sPath) { boolean flag = false; File file = new File(sPath); // 路径为文件且不为空则进行删除 if (file.isFile() && file.exists()) { file.delete(); flag = true; } return flag; } /** * 删除目录(文件夹)以及目录下的文件 * * @param sPath 被删除目录的文件路径 * @return 目录删除成功返回true,否则返回false */ public static boolean deleteDirectory(String sPath) { //如果sPath不以文件分隔符结尾,自动添加文件分隔符 if (!sPath.endsWith(File.separator)) { sPath = sPath + File.separator; } File dirFile = new File(sPath); //如果dir对应的文件不存在,或者不是一个目录,则退出 if (!dirFile.exists() || !dirFile.isDirectory()) { return false; } boolean flag = true; //删除文件夹下的所有文件(包括子目录) File[] files = dirFile.listFiles(); for (int i = 0; i < files.length; i++) { //删除子文件 if (files[i].isFile()) { flag = deleteFile(files[i].getAbsolutePath()); if (!flag) break; } //删除子目录 else { flag = deleteDirectory(files[i].getAbsolutePath()); if (!flag) break; } } if (!flag) return false; //删除当前目录 if (dirFile.delete()) { return true; } else { return false; } } }