package com.ruoyi.utils; import com.ruoyi.common.config.RuoYiConfig; import com.ruoyi.common.utils.DateUtils; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.file.FileTypeUtils; import com.ruoyi.common.utils.file.FileUploadUtils; import com.ruoyi.common.utils.file.MimeTypeUtils; import com.ruoyi.common.utils.uuid.IdUtils; import org.apache.commons.io.FilenameUtils; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.ArrayUtils; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.*; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Paths; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Objects; import java.util.stream.Stream; /** * 文件处理工具类 * * @author ruoyi */ public class FileUtils { public static String FILENAME_PATTERN = "[a-zA-Z0-9_\\-\\|\\.\\u4e00-\\u9fa5]+"; /** * 输出指定文件的byte数组 * * @param filePath 文件路径 * @param os 输出流 * @return */ public static void writeBytes(String filePath, OutputStream os) throws IOException { FileInputStream fis = null; try { File file = new File(filePath); if (!file.exists()) { throw new FileNotFoundException(filePath); } fis = new FileInputStream(file); byte[] b = new byte[1024]; int length; while ((length = fis.read(b)) > 0) { os.write(b, 0, length); } } catch (IOException e) { throw e; } finally { IOUtils.close(os); IOUtils.close(fis); } } /** * 写数据到文件中 * * @param data 数据 * @return 目标文件 * @throws IOException IO异常 */ public static String writeImportBytes(byte[] data) throws IOException { return writeBytes(data, RuoYiConfig.getImportPath()); } /** * 写数据到文件中 * * @param data 数据 * @param uploadDir 目标文件 * @return 目标文件 * @throws IOException IO异常 */ public static String writeBytes(byte[] data, String uploadDir) throws IOException { FileOutputStream fos = null; String pathName = ""; try { String extension = getFileExtendName(data); pathName = DateUtils.datePath() + "/" + IdUtils.fastUUID() + "." + extension; File file = FileUploadUtils.getAbsoluteFile(uploadDir, pathName); fos = new FileOutputStream(file); fos.write(data); } finally { IOUtils.close(fos); } return FileUploadUtils.getPathFileName(uploadDir, pathName); } /** * 删除文件 * * @param filePath 文件 * @return */ public static boolean deleteFile(String filePath) { boolean flag = false; File file = new File(filePath); // 路径为文件且不为空则进行删除 if (file.isFile() && file.exists()) { flag = file.delete(); } return flag; } /** * 文件名称验证 * * @param filename 文件名称 * @return true 正常 false 非法 */ public static boolean isValidFilename(String filename) { return filename.matches(FILENAME_PATTERN); } /** * 检查文件是否可下载 * * @param resource 需要下载的文件 * @return true 正常 false 非法 */ public static boolean checkAllowDownload(String resource) { // 禁止目录上跳级别 if (StringUtils.contains(resource, "..")) { return false; } // 检查允许下载的文件规则 if (ArrayUtils.contains(MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION, FileTypeUtils.getFileType(resource))) { return true; } // 不在允许下载的文件规则 return false; } /** * 下载文件名重新编码 * * @param request 请求对象 * @param fileName 文件名 * @return 编码后的文件名 */ public static String setFileDownloadHeader(HttpServletRequest request, String fileName) throws UnsupportedEncodingException { final String agent = request.getHeader("USER-AGENT"); String filename = fileName; if (agent.contains("MSIE")) { // IE浏览器 filename = URLEncoder.encode(filename, "utf-8"); filename = filename.replace("+", " "); } else if (agent.contains("Firefox")) { // 火狐浏览器 filename = new String(fileName.getBytes(), "ISO8859-1"); } else if (agent.contains("Chrome")) { // google浏览器 filename = URLEncoder.encode(filename, "utf-8"); } else { // 其它浏览器 filename = URLEncoder.encode(filename, "utf-8"); } return filename; } /** * 下载文件名重新编码 * * @param response 响应对象 * @param realFileName 真实文件名 */ public static void setAttachmentResponseHeader(HttpServletResponse response, String realFileName) throws UnsupportedEncodingException { String percentEncodedFileName = percentEncode(realFileName); StringBuilder contentDispositionValue = new StringBuilder(); contentDispositionValue.append("attachment; filename=") .append(percentEncodedFileName) .append(";") .append("filename*=") .append("utf-8''") .append(percentEncodedFileName); response.addHeader("Access-Control-Expose-Headers", "Content-Disposition,download-filename"); response.setHeader("Content-disposition", contentDispositionValue.toString()); response.setHeader("download-filename", percentEncodedFileName); } /** * 百分号编码工具方法 * * @param s 需要百分号编码的字符串 * @return 百分号编码后的字符串 */ public static String percentEncode(String s) throws UnsupportedEncodingException { String encode = URLEncoder.encode(s, StandardCharsets.UTF_8.toString()); return encode.replaceAll("\\+", "%20"); } /** * 获取图像后缀 * * @param photoByte 图像数据 * @return 后缀名 */ public static String getFileExtendName(byte[] photoByte) { String strFileExtendName = "jpg"; if ((photoByte[0] == 71) && (photoByte[1] == 73) && (photoByte[2] == 70) && (photoByte[3] == 56) && ((photoByte[4] == 55) || (photoByte[4] == 57)) && (photoByte[5] == 97)) { strFileExtendName = "gif"; } else if ((photoByte[6] == 74) && (photoByte[7] == 70) && (photoByte[8] == 73) && (photoByte[9] == 70)) { strFileExtendName = "jpg"; } else if ((photoByte[0] == 66) && (photoByte[1] == 77)) { strFileExtendName = "bmp"; } else if ((photoByte[1] == 80) && (photoByte[2] == 78) && (photoByte[3] == 71)) { strFileExtendName = "png"; } return strFileExtendName; } /** * 获取文件名称 /profile/upload/2022/04/16/ruoyi.png -- ruoyi.png * * @param fileName 路径名称 * @return 没有文件路径的名称 */ public static String getName(String fileName) { if (fileName == null) { return null; } int lastUnixPos = fileName.lastIndexOf('/'); int lastWindowsPos = fileName.lastIndexOf('\\'); int index = Math.max(lastUnixPos, lastWindowsPos); return fileName.substring(index + 1); } /** * 获取不带后缀文件名称 /profile/upload/2022/04/16/ruoyi.png -- ruoyi * * @param fileName 路径名称 * @return 没有文件路径和后缀的名称 */ public static String getNameNotSuffix(String fileName) { if (fileName == null) { return null; } String baseName = FilenameUtils.getBaseName(fileName); return baseName; } /** *

获取指定文件夹下所有文件,不含文件夹

* @param dirFilePath 文件夹路径 * @return */ public static List getAllFile(String dirFilePath){ if(StringUtils.isBlank(dirFilePath)) return null; return getAllFile(new File(dirFilePath)); } /** *

获取指定文件夹下所有文件,不含文件夹

* @param dirFile 文件夹 * @return */ public static List getAllFile(File dirFile){ // 如果文件夹不存在或着不是文件夹,则返回 null if(Objects.isNull(dirFile) || !dirFile.exists() || dirFile.isFile()) return null; File[] childrenFiles = dirFile.listFiles(); if(Objects.isNull(childrenFiles) || childrenFiles.length == 0) return null; List files = new ArrayList<>(); for(File childFile : childrenFiles) { // 如果时文件,直接添加到结果集合 if(childFile.isFile()) { files.add(childFile); } /*else { // 如果是文件夹,则将其内部文件添加进结果集合 List cFiles = getAllFile(childFile); if(Objects.isNull(cFiles) || cFiles.isEmpty()) continue; files.addAll(cFiles); }*/ } return files; } /** * 在指定ftp服务器路径下创建空白文件并写入方法体 * @param path 路径 * @return */ public static String createFtpFile(String path,String checkTitle,String checkHead) throws IOException { Date date=new Date(); SimpleDateFormat sdf=new SimpleDateFormat("yyyyMMddHHmmss"); SimpleDateFormat sdf2=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String time=sdf.format(date); String headTime=sdf2.format(date); checkHead=checkHead+"0;"+headTime; byte[] byte1= DESUtil.encrypt(checkHead.getBytes(StandardCharsets.UTF_8),"xxxltk00"); String bakName=RuoYiConfig.getFtpPath()+"/bak/"+path+"/"+checkTitle+time+".txt"; String sendName=RuoYiConfig.getFtpPath()+"/send/"+path+"/"+checkTitle+time+".tmp"; String fileName=checkTitle+time+".txt"; String line=DESUtil.byteToHex(byte1); Files.write(Paths.get(bakName),line.getBytes(StandardCharsets.UTF_8)); Files.write(Paths.get(sendName),line.getBytes(StandardCharsets.UTF_8)); return fileName; } /** * 在send路径下创建空白文件并写入方法体 * @param path 路径 * @return */ public static String createSendFile(String path,String checkTitle,String checkHead)throws IOException{ Date date=new Date(); SimpleDateFormat sdf=new SimpleDateFormat("yyyyMMddHHmmss"); SimpleDateFormat sdf2=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String time=sdf.format(date); String headTime=sdf2.format(date); checkHead=checkHead+0+";"+headTime; String sendName=RuoYiConfig.getFtpPath()+"/send/"+path+"/"+checkTitle+time+".txt"; Files.write(Paths.get(sendName),checkHead.getBytes(StandardCharsets.UTF_8)); moveFile(RuoYiConfig.getFtpPath()+"/send/"+path+"/"+checkTitle+time+".txt",RuoYiConfig.getFtpPath()+"/send/"+path+"/"+checkTitle+time+".tmp"); return sendName; } /** * 在send路径下创建空白文件并写入方法体 * @param path 路径 * @return */ public static String createNewCheckHead(String path,String checkHead,String oldName)throws IOException{ Date date=new Date(); SimpleDateFormat sdf=new SimpleDateFormat("yyyyMMddHHmmss"); SimpleDateFormat sdf2=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String headTime=sdf2.format(date); checkHead=checkHead+0+";"+headTime; byte[] byte1= DESUtil.encrypt(checkHead.getBytes(StandardCharsets.UTF_8),"xxxltk00"); String line=DESUtil.byteToHex(byte1); String sendName=RuoYiConfig.getFtpPath()+"/send/"+path+"/"+oldName; Files.write(Paths.get(sendName),line.getBytes(StandardCharsets.UTF_8)); String tmpName=sendName.substring(0,sendName.length()-18)+sdf.format(date)+".tmp"; moveFile(sendName,tmpName); return tmpName; } /** * 将指定文件移动到指定目录下 * @param oldPath 旧文件路径 * @param newPath 新文件路径 * @return */ public static boolean moveFile(String oldPath,String newPath) { File oldFile=new File(oldPath); File newFile=new File(newPath); Boolean flag=oldFile.renameTo(newFile); return flag; } /** * 复制文件 * @param oldDir 原来的文件 * @param newDir 复制到的文件 */ public static void copyFile(File oldDir, File newDir) { BufferedInputStream bufferedInputStream = null; BufferedOutputStream bufferedOutputStream = null; byte[] b = new byte[1024]; try { // 将要复制文件输入到缓冲输入流 bufferedInputStream = new BufferedInputStream(new FileInputStream(oldDir)); // 将复制的文件定义为缓冲输出流 bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(newDir)); // 定义字节数 int len; while ((len = bufferedInputStream.read(b)) > -1) { // 写入文件 bufferedOutputStream.write(b, 0, len); } //刷新此缓冲输出流 bufferedOutputStream.flush(); } catch (IOException e) { e.printStackTrace(); } finally { if (bufferedInputStream != null) { try { // 关闭流 bufferedInputStream.close(); } catch (IOException e) { e.printStackTrace(); } } if (bufferedOutputStream != null) { try { bufferedOutputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } } public static List readFile(String fileName) throws IOException { // 读取文件内容到Stream流中,按行读取 Stream lines = Files.lines(Paths.get(fileName)); Listlist=new ArrayList<>(); //顺序进行数据处理 lines.parallel().forEachOrdered(ele -> { list.add(ele); }); lines.close(); return list; } /** * File转byte[]数组 * * @param file * @return */ public static byte[] fileTobyte(File file) { if (file == null) { return null; } FileInputStream fileInputStream = null; ByteArrayOutputStream byteArrayOutputStream = null; try { fileInputStream = new FileInputStream(file); byteArrayOutputStream = new ByteArrayOutputStream(); byte[] b = new byte[1024]; int n; while ((n = fileInputStream.read(b)) != -1) { byteArrayOutputStream.write(b, 0 , n); } return byteArrayOutputStream.toByteArray(); } catch (Exception e) { e.printStackTrace(); } finally { if (byteArrayOutputStream != null) { try { byteArrayOutputStream.close(); } catch (IOException e) { e.printStackTrace(); } } if (fileInputStream != null) { try { fileInputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } return null; } /** * byte[]数组转File * * @param bytes * @param fileFullPath * @return */ public static File byteTofile(byte[] bytes, String fileFullPath) { if (bytes == null) { return null; } FileOutputStream fileOutputStream = null; try { File file = new File(fileFullPath); //判断文件是否存在 if (file.exists()) { file.mkdirs(); } fileOutputStream = new FileOutputStream(file); fileOutputStream.write(bytes); return file; } catch (Exception e) { e.printStackTrace(); } finally { if (fileOutputStream != null) { try { fileOutputStream.close(); } catch (IOException ioe) { ioe.printStackTrace(); } } } return null; } }