FileUtils.java 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. package com.ruoyi.common.utils.file;
  2. import java.io.File;
  3. import java.io.FileInputStream;
  4. import java.io.FileNotFoundException;
  5. import java.io.FileOutputStream;
  6. import java.io.IOException;
  7. import java.io.OutputStream;
  8. import java.io.UnsupportedEncodingException;
  9. import java.net.URLEncoder;
  10. import java.nio.charset.StandardCharsets;
  11. import javax.servlet.http.HttpServletRequest;
  12. import javax.servlet.http.HttpServletResponse;
  13. import org.apache.commons.io.IOUtils;
  14. import org.apache.commons.lang3.ArrayUtils;
  15. import com.ruoyi.common.config.RuoYiConfig;
  16. import com.ruoyi.common.utils.DateUtils;
  17. import com.ruoyi.common.utils.StringUtils;
  18. import com.ruoyi.common.utils.uuid.IdUtils;
  19. import org.apache.commons.io.FilenameUtils;
  20. /**
  21. * 文件处理工具类
  22. *
  23. * @author ruoyi
  24. */
  25. public class FileUtils
  26. {
  27. public static String FILENAME_PATTERN = "[a-zA-Z0-9_\\-\\|\\.\\u4e00-\\u9fa5]+";
  28. /**
  29. * 输出指定文件的byte数组
  30. *
  31. * @param filePath 文件路径
  32. * @param os 输出流
  33. * @return
  34. */
  35. public static void writeBytes(String filePath, OutputStream os) throws IOException
  36. {
  37. FileInputStream fis = null;
  38. try
  39. {
  40. File file = new File(filePath);
  41. if (!file.exists())
  42. {
  43. throw new FileNotFoundException(filePath);
  44. }
  45. fis = new FileInputStream(file);
  46. byte[] b = new byte[1024];
  47. int length;
  48. while ((length = fis.read(b)) > 0)
  49. {
  50. os.write(b, 0, length);
  51. }
  52. }
  53. catch (IOException e)
  54. {
  55. throw e;
  56. }
  57. finally
  58. {
  59. IOUtils.close(os);
  60. IOUtils.close(fis);
  61. }
  62. }
  63. /**
  64. * 写数据到文件中
  65. *
  66. * @param data 数据
  67. * @return 目标文件
  68. * @throws IOException IO异常
  69. */
  70. public static String writeImportBytes(byte[] data) throws IOException
  71. {
  72. return writeBytes(data, RuoYiConfig.getImportPath());
  73. }
  74. /**
  75. * 写数据到文件中
  76. *
  77. * @param data 数据
  78. * @param uploadDir 目标文件
  79. * @return 目标文件
  80. * @throws IOException IO异常
  81. */
  82. public static String writeBytes(byte[] data, String uploadDir) throws IOException
  83. {
  84. FileOutputStream fos = null;
  85. String pathName = "";
  86. try
  87. {
  88. String extension = getFileExtendName(data);
  89. pathName = DateUtils.datePath() + "/" + IdUtils.fastUUID() + "." + extension;
  90. File file = FileUploadUtils.getAbsoluteFile(uploadDir, pathName);
  91. fos = new FileOutputStream(file);
  92. fos.write(data);
  93. }
  94. finally
  95. {
  96. IOUtils.close(fos);
  97. }
  98. return FileUploadUtils.getPathFileName(uploadDir, pathName);
  99. }
  100. /**
  101. * 删除文件
  102. *
  103. * @param filePath 文件
  104. * @return
  105. */
  106. public static boolean deleteFile(String filePath)
  107. {
  108. boolean flag = false;
  109. File file = new File(filePath);
  110. // 路径为文件且不为空则进行删除
  111. if (file.isFile() && file.exists())
  112. {
  113. file.delete();
  114. flag = true;
  115. }
  116. return flag;
  117. }
  118. /**
  119. * 文件名称验证
  120. *
  121. * @param filename 文件名称
  122. * @return true 正常 false 非法
  123. */
  124. public static boolean isValidFilename(String filename)
  125. {
  126. return filename.matches(FILENAME_PATTERN);
  127. }
  128. /**
  129. * 检查文件是否可下载
  130. *
  131. * @param resource 需要下载的文件
  132. * @return true 正常 false 非法
  133. */
  134. public static boolean checkAllowDownload(String resource)
  135. {
  136. // 禁止目录上跳级别
  137. if (StringUtils.contains(resource, ".."))
  138. {
  139. return false;
  140. }
  141. // 检查允许下载的文件规则
  142. if (ArrayUtils.contains(MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION, FileTypeUtils.getFileType(resource)))
  143. {
  144. return true;
  145. }
  146. // 不在允许下载的文件规则
  147. return false;
  148. }
  149. /**
  150. * 下载文件名重新编码
  151. *
  152. * @param request 请求对象
  153. * @param fileName 文件名
  154. * @return 编码后的文件名
  155. */
  156. public static String setFileDownloadHeader(HttpServletRequest request, String fileName) throws UnsupportedEncodingException
  157. {
  158. final String agent = request.getHeader("USER-AGENT");
  159. String filename = fileName;
  160. if (agent.contains("MSIE"))
  161. {
  162. // IE浏览器
  163. filename = URLEncoder.encode(filename, "utf-8");
  164. filename = filename.replace("+", " ");
  165. }
  166. else if (agent.contains("Firefox"))
  167. {
  168. // 火狐浏览器
  169. filename = new String(fileName.getBytes(), "ISO8859-1");
  170. }
  171. else if (agent.contains("Chrome"))
  172. {
  173. // google浏览器
  174. filename = URLEncoder.encode(filename, "utf-8");
  175. }
  176. else
  177. {
  178. // 其它浏览器
  179. filename = URLEncoder.encode(filename, "utf-8");
  180. }
  181. return filename;
  182. }
  183. /**
  184. * 下载文件名重新编码
  185. *
  186. * @param response 响应对象
  187. * @param realFileName 真实文件名
  188. */
  189. public static void setAttachmentResponseHeader(HttpServletResponse response, String realFileName) throws UnsupportedEncodingException
  190. {
  191. String percentEncodedFileName = percentEncode(realFileName);
  192. StringBuilder contentDispositionValue = new StringBuilder();
  193. contentDispositionValue.append("attachment; filename=")
  194. .append(percentEncodedFileName)
  195. .append(";")
  196. .append("filename*=")
  197. .append("utf-8''")
  198. .append(percentEncodedFileName);
  199. response.addHeader("Access-Control-Expose-Headers", "Content-Disposition,download-filename");
  200. response.setHeader("Content-disposition", contentDispositionValue.toString());
  201. response.setHeader("download-filename", percentEncodedFileName);
  202. }
  203. /**
  204. * 百分号编码工具方法
  205. *
  206. * @param s 需要百分号编码的字符串
  207. * @return 百分号编码后的字符串
  208. */
  209. public static String percentEncode(String s) throws UnsupportedEncodingException
  210. {
  211. String encode = URLEncoder.encode(s, StandardCharsets.UTF_8.toString());
  212. return encode.replaceAll("\\+", "%20");
  213. }
  214. /**
  215. * 获取图像后缀
  216. *
  217. * @param photoByte 图像数据
  218. * @return 后缀名
  219. */
  220. public static String getFileExtendName(byte[] photoByte)
  221. {
  222. String strFileExtendName = "jpg";
  223. if ((photoByte[0] == 71) && (photoByte[1] == 73) && (photoByte[2] == 70) && (photoByte[3] == 56)
  224. && ((photoByte[4] == 55) || (photoByte[4] == 57)) && (photoByte[5] == 97))
  225. {
  226. strFileExtendName = "gif";
  227. }
  228. else if ((photoByte[6] == 74) && (photoByte[7] == 70) && (photoByte[8] == 73) && (photoByte[9] == 70))
  229. {
  230. strFileExtendName = "jpg";
  231. }
  232. else if ((photoByte[0] == 66) && (photoByte[1] == 77))
  233. {
  234. strFileExtendName = "bmp";
  235. }
  236. else if ((photoByte[1] == 80) && (photoByte[2] == 78) && (photoByte[3] == 71))
  237. {
  238. strFileExtendName = "png";
  239. }
  240. return strFileExtendName;
  241. }
  242. /**
  243. * 获取名称
  244. * 例如: /profile/upload/2022/04/16/ruoyi.png, 返回: ruoyi.png
  245. * @param fileName 路径名称
  246. * @return 没有文件路径的名称
  247. */
  248. public static String getName(String fileName)
  249. {
  250. if (fileName == null)
  251. {
  252. return null;
  253. }
  254. int lastUnixPos = fileName.lastIndexOf('/');
  255. int lastWindowsPos = fileName.lastIndexOf('\\');
  256. int index = Math.max(lastUnixPos, lastWindowsPos);
  257. return fileName.substring(index + 1);
  258. }
  259. /**
  260. * 获取名称
  261. * 例如: /profile/upload/2022/04/16/ruoyi.png, 返回: ruoyi
  262. * @param fileName 路径名称
  263. * @return 没有文件路径的名称
  264. */
  265. public static String getNameNotSuffix(String fileName) {
  266. if (fileName == null) {
  267. return null;
  268. }
  269. String baseName = FilenameUtils.getBaseName(fileName);
  270. return baseName;
  271. }
  272. }