CommonUtil.java 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510
  1. package org.springblade.common.utils;
  2. import cn.hutool.core.io.FileUtil;
  3. import cn.hutool.http.HttpUtil;
  4. import com.alibaba.fastjson.JSON;
  5. import com.alibaba.fastjson.JSONObject;
  6. import com.drew.imaging.ImageMetadataReader;
  7. import com.drew.imaging.ImageProcessingException;
  8. import com.drew.metadata.Metadata;
  9. import com.drew.metadata.exif.ExifIFD0Directory;
  10. import org.apache.commons.lang.StringUtils;
  11. import org.springframework.util.CollectionUtils;
  12. import javax.imageio.IIOImage;
  13. import javax.imageio.ImageIO;
  14. import javax.imageio.ImageWriteParam;
  15. import javax.imageio.ImageWriter;
  16. import java.awt.*;
  17. import java.awt.geom.AffineTransform;
  18. import java.awt.image.AffineTransformOp;
  19. import java.awt.image.BufferedImage;
  20. import java.io.*;
  21. import java.math.BigDecimal;
  22. import java.net.HttpURLConnection;
  23. import java.net.URL;
  24. import java.net.URLConnection;
  25. import java.time.LocalDate;
  26. import java.util.*;
  27. import java.util.List;
  28. import java.util.regex.Matcher;
  29. import java.util.regex.Pattern;
  30. import java.util.stream.Collectors;
  31. import java.util.stream.Stream;
  32. import java.util.zip.ZipEntry;
  33. import java.util.zip.ZipOutputStream;
  34. import com.drew.metadata.MetadataException;
  35. /**
  36. * 通用工具类
  37. *
  38. * @author Chill
  39. */
  40. public class CommonUtil {
  41. public static Boolean checkBigDecimal(Object value) {
  42. try {
  43. if (value != null && StringUtils.isNotEmpty(value.toString())) {
  44. new BigDecimal(value.toString());
  45. return true;
  46. }
  47. } catch (Exception e) {
  48. e.printStackTrace();
  49. }
  50. return false;
  51. }
  52. public static void removeFile(List<String> removeList) {
  53. for (String fileUrl : removeList) {
  54. try {
  55. FileUtil.del(new File(fileUrl));
  56. } catch (Exception e) {
  57. e.printStackTrace();
  58. }
  59. }
  60. }
  61. public static String handleNull(Object obj) {
  62. if (null == obj) {
  63. return "";
  64. } else {
  65. return obj.toString().trim();
  66. }
  67. }
  68. public static String join(Object... args) {
  69. if (args != null) {
  70. if (args.length > 2) {
  71. List<String> list = Arrays.stream(args).limit(args.length - 1).map(CommonUtil::handleNull).collect(Collectors.toList());
  72. String split = handleNull(args[args.length - 1]);
  73. return join(list, split);
  74. } else {
  75. return handleNull(args[0]);
  76. }
  77. } else {
  78. return "";
  79. }
  80. }
  81. public static String join(List<String> list, String split) {
  82. StringBuilder sb = new StringBuilder();
  83. if (list != null && list.size() > 0) {
  84. for (String str : list) {
  85. if (StringUtils.isNotEmpty(str)) {
  86. sb.append(str).append(split);
  87. }
  88. }
  89. if (sb.length() > 0 && StringUtils.isNotEmpty(split)) {
  90. sb.delete(sb.length() - split.length(), sb.length());
  91. }
  92. }
  93. return sb.toString();
  94. }
  95. public static Matcher matcher(String regex, String value) {
  96. Pattern pattern = Pattern.compile(regex);
  97. return pattern.matcher(value);
  98. }
  99. /**
  100. * 根据OSS文件路径获取文件输入流
  101. */
  102. public static InputStream getOSSInputStream(String urlStr) throws Exception {
  103. //获取OSS文件流
  104. urlStr = replaceOssUrl(urlStr);
  105. URL imageUrl = new URL(urlStr);
  106. try {
  107. HttpURLConnection conn = (HttpURLConnection) imageUrl.openConnection();
  108. conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
  109. return conn.getInputStream();
  110. } catch (Exception e) {
  111. return null;
  112. }
  113. }
  114. /**
  115. * 根据OSS文件路径获取文件输入流
  116. */
  117. public static InputStream getOSSInputStreamTow(String urlStr) throws Exception {
  118. //获取OSS文件流
  119. urlStr = replaceOssUrl(urlStr);
  120. URL imageUrl = new URL(urlStr);
  121. HttpURLConnection conn = null;
  122. try {
  123. conn = (HttpURLConnection) imageUrl.openConnection();
  124. conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
  125. return conn.getInputStream();
  126. } catch (IOException e) {
  127. e.printStackTrace();
  128. if (conn != null) {
  129. conn.disconnect(); //关闭网络连接
  130. }
  131. throw new Exception("获取图片输入流失败!URL:" + urlStr, e);
  132. }
  133. }
  134. /**
  135. * 获取字节数组
  136. */
  137. public static byte[] InputStreamToBytes(InputStream is) throws IOException {
  138. BufferedInputStream bis = new BufferedInputStream(is);
  139. ByteArrayOutputStream os = new ByteArrayOutputStream();
  140. int date = -1;
  141. while ((date = bis.read()) != -1) {
  142. os.write(date);
  143. }
  144. return os.toByteArray();
  145. }
  146. /**
  147. * 随机生成短信验证码
  148. *
  149. * @param length 生成长度
  150. */
  151. public static String getCharAndNumber(int length) {
  152. StringBuilder val = new StringBuilder();
  153. Random random = new Random();
  154. for (int i = 0; i < length; i++) {
  155. String charOrNum = random.nextInt(2) % 2 == 0 ? "char" : "num";
  156. if ("char".equalsIgnoreCase(charOrNum)) {
  157. int choice = random.nextInt(2) % 2 == 0 ? 65 : 97;
  158. val.append((char) (choice + random.nextInt(26)));
  159. } else {
  160. val.append(random.nextInt(10));
  161. }
  162. }
  163. return val.toString();
  164. }
  165. /**
  166. * 判断参数是否是数字
  167. *
  168. * @param value 需要判断数据
  169. * @return 判断结果,数字则为true,反之false
  170. */
  171. public static boolean checkIsBigDecimal(Object value) {
  172. try {
  173. if (value != null && StringUtils.isNotEmpty(String.valueOf(value))) {
  174. new BigDecimal(String.valueOf(value));
  175. return true;
  176. } else {
  177. return false;
  178. }
  179. } catch (Exception e) {
  180. return false;
  181. }
  182. }
  183. /**
  184. * 根据每页信息分组
  185. */
  186. public static <T> List<List<T>> getBatchSize(List<T> allIds, int size) {
  187. List<List<T>> batchIds = new ArrayList<>();
  188. if (allIds == null || allIds.size() == 0 || size <= 0) {
  189. return batchIds;
  190. }
  191. int i = 0;
  192. List<T> tmp = new ArrayList<>();
  193. for (T map : allIds) {
  194. tmp.add(map);
  195. i++;
  196. if (i % size == 0 || i == allIds.size()) {
  197. batchIds.add(tmp);
  198. tmp = new ArrayList<>();
  199. }
  200. }
  201. return batchIds;
  202. }
  203. /**
  204. * @param src
  205. * @throws IOException
  206. * @throws ClassNotFoundException
  207. */
  208. public static <T> List<T> deepCopy(List<T> src) throws IOException, ClassNotFoundException {
  209. ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
  210. ObjectOutputStream out = new ObjectOutputStream(byteOut);
  211. out.writeObject(src);
  212. ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray());
  213. ObjectInputStream in = new ObjectInputStream(byteIn);
  214. @SuppressWarnings("unchecked")
  215. List<T> dest = (List<T>) in.readObject();
  216. return dest;
  217. }
  218. /**
  219. * Description: Java8 Stream分割list集合
  220. *
  221. * @param list 集合数据
  222. * @param splitSize 几个分割一组
  223. * @return 集合分割后的集合
  224. */
  225. public static <T> List<List<T>> splitList(List<T> list, int splitSize) {
  226. //判断集合是否为空
  227. if (CollectionUtils.isEmpty(list))
  228. return Collections.emptyList();
  229. //计算分割后的大小
  230. int maxSize = (list.size() + splitSize - 1) / splitSize;
  231. //开始分割
  232. return Stream.iterate(0, n -> n + 1)
  233. .limit(maxSize)
  234. .parallel()
  235. .map(a -> list.parallelStream().skip(a * splitSize).limit(splitSize).collect(Collectors.toList()))
  236. .filter(b -> !b.isEmpty())
  237. .collect(Collectors.toList());
  238. }
  239. /**
  240. * 流写入文件
  241. *
  242. * @param inputStream 文件输入流
  243. * @param file 输出文件
  244. */
  245. public static void inputStreamToFile(InputStream inputStream, File file) {
  246. try {
  247. OutputStream os = new FileOutputStream(file);
  248. int bytesRead = 0;
  249. byte[] buffer = new byte[8192];
  250. while ((bytesRead = inputStream.read(buffer, 0, 8192)) != -1) {
  251. os.write(buffer, 0, bytesRead);
  252. }
  253. os.close();
  254. inputStream.close();
  255. } catch (Exception e) {
  256. e.printStackTrace();
  257. }
  258. }
  259. /**
  260. * 删除文件夹下所有文件
  261. *
  262. * @param path
  263. * @return
  264. */
  265. public static boolean deleteDir(String path) {
  266. File file = new File(path);
  267. if (!file.exists()) {//判断是否待删除目录是否存在
  268. System.err.println("The dir are not exists!");
  269. return false;
  270. }
  271. String[] content = file.list();//取得当前目录下所有文件和文件夹
  272. for (String name : content) {
  273. File temp = new File(path, name);
  274. if (temp.isDirectory()) {//判断是否是目录
  275. deleteDir(temp.getAbsolutePath());//递归调用,删除目录里的内容
  276. temp.delete();//删除空目录
  277. } else {
  278. if (!temp.delete()) {//直接删除文件
  279. System.err.println("Failed to delete " + name);
  280. }
  281. }
  282. }
  283. return true;
  284. }
  285. /**
  286. * 压缩指定路径下的文件夹
  287. *
  288. * @param filesPath
  289. * @throws Exception
  290. */
  291. public static void packageZip(String filesPath) throws Exception {
  292. // 要被压缩的文件夹
  293. File file = new File(filesPath); //需要压缩的文件夹
  294. File zipFile = new File(filesPath + ".zip"); //放于和需要压缩的文件夹同级目录
  295. ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(zipFile));
  296. isDirectory(file, zipOut, "", true); //判断是否为文件夹
  297. zipOut.close();
  298. }
  299. public static void isDirectory(File file, ZipOutputStream zipOutputStream, String filePath, boolean flag) throws IOException {
  300. //判断是否为问加减
  301. if (file.isDirectory()) {
  302. File[] files = file.listFiles(); //获取该文件夹下所有文件(包含文件夹)
  303. filePath = flag == true ? file.getName() : filePath + File.separator + file.getName(); //首次为选中的文件夹,即根目录,之后递归实现拼接目录
  304. for (int i = 0; i < files.length; ++i) {
  305. //判断子文件是否为文件夹
  306. if (files[i].isDirectory()) {
  307. //进入递归,flag置false 即当前文件夹下仍包含文件夹
  308. isDirectory(files[i], zipOutputStream, filePath, false);
  309. } else {
  310. //不为文件夹则进行压缩
  311. InputStream input = new FileInputStream(files[i]);
  312. zipOutputStream.putNextEntry(new ZipEntry(filePath + File.separator + files[i].getName()));
  313. int temp = 0;
  314. while ((temp = input.read()) != -1) {
  315. zipOutputStream.write(temp);
  316. }
  317. input.close();
  318. }
  319. }
  320. } else {
  321. //将子文件夹下的文件进行压缩
  322. InputStream input = new FileInputStream(file);
  323. zipOutputStream.putNextEntry(new ZipEntry(file.getPath()));
  324. int temp = 0;
  325. while ((temp = input.read()) != -1) {
  326. zipOutputStream.write(temp);
  327. }
  328. input.close();
  329. }
  330. }
  331. /**
  332. * @param urlStr
  333. * @return 返回Url资源大小
  334. * @throws IOException
  335. */
  336. public static long getResourceLength(String urlStr) throws IOException {
  337. URL url = new URL(urlStr);
  338. URLConnection urlConnection = url.openConnection();
  339. urlConnection.connect();
  340. //返回响应报文头字段Content-Length的值
  341. return urlConnection.getContentLength();
  342. }
  343. /**
  344. * 图片缩放、压缩、旋转处理
  345. *
  346. * @param imageData
  347. * @return
  348. * @throws IOException
  349. * @throws ImageProcessingException
  350. * @throws MetadataException
  351. */
  352. public static byte[] compressImage(byte[] imageData) throws IOException, ImageProcessingException, MetadataException {
  353. // 读取原始图像(处理旋转问题)
  354. Metadata metadata = ImageMetadataReader.readMetadata(new ByteArrayInputStream(imageData));
  355. if (metadata.containsDirectoryOfType(ExifIFD0Directory.class)) {
  356. ExifIFD0Directory exifIFD0Directory = metadata.getFirstDirectoryOfType(ExifIFD0Directory.class);
  357. if (exifIFD0Directory.containsTag(ExifIFD0Directory.TAG_ORIENTATION)) {
  358. // 获取 Orientation 标签的值
  359. int orientation = exifIFD0Directory.getInt(ExifIFD0Directory.TAG_ORIENTATION);
  360. // 需要旋转图片
  361. BufferedImage originalImage = ImageIO.read(new ByteArrayInputStream(imageData));
  362. AffineTransform transform = new AffineTransform();
  363. if (orientation == 6) {
  364. transform.rotate(Math.PI / 2, originalImage.getWidth() / 2, originalImage.getHeight() / 2);
  365. } else if (orientation == 8) {
  366. transform.rotate(-Math.PI / 2, originalImage.getWidth() / 2, originalImage.getHeight() / 2);
  367. }
  368. AffineTransformOp op = new AffineTransformOp(transform, AffineTransformOp.TYPE_BILINEAR);
  369. originalImage = op.filter(originalImage, null);
  370. ByteArrayOutputStream baos = new ByteArrayOutputStream();
  371. ImageIO.write(originalImage, "jpg", baos);
  372. imageData = baos.toByteArray();
  373. }
  374. }
  375. // 缩放图像
  376. String formatName = "JPEG";
  377. ByteArrayInputStream bais = new ByteArrayInputStream(imageData);
  378. BufferedImage originalImage = ImageIO.read(bais);
  379. long sizeLimit = 366912; //358KB
  380. int width = 768;
  381. int height = 1024;
  382. Image scaledImage = originalImage.getScaledInstance(width, height, Image.SCALE_SMOOTH);
  383. BufferedImage resizedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
  384. resizedImage.getGraphics().drawImage(scaledImage, 0, 0, null);
  385. // 压缩图像
  386. ByteArrayOutputStream baos = new ByteArrayOutputStream();
  387. ImageIO.write(resizedImage, formatName, baos);
  388. if (baos.size() <= sizeLimit) {
  389. // 图片大小已经小于等于目标大小,直接返回原始数据
  390. return baos.toByteArray();
  391. }
  392. float quality = 0.9f; // 初始化压缩质量
  393. int retries = 10; // 最多尝试 10 次
  394. while (baos.size() > sizeLimit && retries > 0) {
  395. // 压缩图像并重新计算压缩质量
  396. byte[] data = baos.toByteArray();
  397. bais = new ByteArrayInputStream(data);
  398. BufferedImage compressedImage = ImageIO.read(bais);
  399. baos.reset();
  400. ImageWriter writer = null;
  401. Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName(formatName);
  402. if (writers.hasNext()) {
  403. writer = writers.next();
  404. } else {
  405. throw new IllegalArgumentException("Unsupported image format: " + formatName);
  406. }
  407. ImageWriteParam writeParam = writer.getDefaultWriteParam();
  408. writeParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
  409. writeParam.setCompressionQuality(quality);
  410. writer.setOutput(ImageIO.createImageOutputStream(baos));
  411. writer.write(null, new IIOImage(compressedImage, null, null), writeParam);
  412. writer.dispose();
  413. float ratio = sizeLimit * 1.0f / baos.size();
  414. quality *= Math.sqrt(ratio);
  415. retries--;
  416. }
  417. return baos.toByteArray();
  418. }
  419. /**
  420. * 根据起止日期获取工作日
  421. * @return
  422. */
  423. public static int getWorkDays(LocalDate startTime,LocalDate endTime){
  424. StringBuilder str = new StringBuilder();
  425. List<String> list = new ArrayList<>();
  426. while (!startTime.equals(endTime)){
  427. str.append("d="+startTime+"&");
  428. list.add(startTime.toString());
  429. startTime = startTime.plusDays(1L);
  430. }
  431. str.append("d="+endTime+"&");
  432. list.add(endTime.toString());
  433. str.append("type=Y");
  434. String post = HttpUtil.get("http://timor.tech/api/holiday/batch?" + str.toString());
  435. JSONObject jsonObject = JSON.parseObject(post).getJSONObject("type");
  436. System.out.println(jsonObject);
  437. int workDays = 0;
  438. for (String s : list) {
  439. Map map = JSONObject.parseObject(jsonObject.get(s).toString(), Map.class);
  440. int type = (int) map.get("type");
  441. if (type == 0 || type == 3){
  442. workDays++;
  443. }
  444. }
  445. return workDays;
  446. }
  447. // 上传文件路径获取
  448. public String getSysFileUrl() {
  449. return "";
  450. }
  451. public static String replaceOssUrl(String url) {
  452. String osName = System.getProperty("os.name");
  453. if (osName != null && osName.toLowerCase().contains("linux")) {
  454. // 如果当前操作系统是Linux系统
  455. Map<String, String> envMap = System.getenv();
  456. if (!envMap.containsKey("linuxtesttest")) {
  457. // 如果当前环境变量不包含linuxtesttest,则替换URL中的oss路径
  458. url = url.replace("oss-cn-hangzhou.aliyuncs.com", "oss-cn-hangzhou-internal.aliyuncs.com");
  459. }
  460. }
  461. //后续删除
  462. System.out.println("replaceOssUrl " + url);
  463. return url;
  464. }
  465. }