ConvertUtil.java 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441
  1. package com.qmth.teachcloud.common.util;
  2. import com.qmth.teachcloud.common.contant.SystemConstant;
  3. import com.qmth.teachcloud.common.enums.ExceptionResultEnum;
  4. import org.apache.pdfbox.pdmodel.PDDocument;
  5. import org.apache.pdfbox.pdmodel.PDPageTree;
  6. import org.apache.pdfbox.rendering.PDFRenderer;
  7. import org.apache.poi.hssf.usermodel.HSSFDateUtil;
  8. import org.apache.poi.ss.usermodel.Cell;
  9. import org.apache.poi.ss.usermodel.CellType;
  10. import org.slf4j.Logger;
  11. import org.slf4j.LoggerFactory;
  12. import org.springframework.data.redis.core.RedisTemplate;
  13. import org.springframework.data.redis.support.atomic.RedisAtomicLong;
  14. import org.springframework.stereotype.Component;
  15. import javax.annotation.Resource;
  16. import javax.imageio.ImageIO;
  17. import javax.servlet.http.HttpServletResponse;
  18. import java.awt.image.BufferedImage;
  19. import java.io.*;
  20. import java.net.URLEncoder;
  21. import java.text.DecimalFormat;
  22. import java.text.SimpleDateFormat;
  23. import java.util.*;
  24. /**
  25. * @Description: 转换工具类
  26. * @Author: CaoZixuan
  27. * @Date: 2021-04-14
  28. */
  29. @Component
  30. public class ConvertUtil {
  31. private final static Logger log = LoggerFactory.getLogger(ConvertUtil.class);
  32. @Resource
  33. RedisTemplate<String, Object> redisTemplate;
  34. // inputStream转outputStream
  35. public static ByteArrayOutputStream parse(final InputStream in) throws Exception {
  36. final ByteArrayOutputStream swapStream = new ByteArrayOutputStream();
  37. int ch;
  38. while ((ch = in.read()) != -1) {
  39. swapStream.write(ch);
  40. }
  41. return swapStream;
  42. }
  43. // outputStream转inputStream
  44. public static ByteArrayInputStream parse(final OutputStream out) {
  45. ByteArrayOutputStream baos = new ByteArrayOutputStream();
  46. baos = (ByteArrayOutputStream) out;
  47. return new ByteArrayInputStream(baos.toByteArray());
  48. }
  49. public static void inputStream2File(InputStream is, File file) throws IOException {
  50. OutputStream os = null;
  51. try {
  52. os = new FileOutputStream(file);
  53. int len = 0;
  54. byte[] buffer = new byte[8192];
  55. while ((len = is.read(buffer)) != -1) {
  56. os.write(buffer, 0, len);
  57. }
  58. } finally {
  59. os.close();
  60. is.close();
  61. }
  62. }
  63. /**
  64. * 转换,解析时间
  65. *
  66. * @param date 日期(考试日期,必须是同一天 example: 2021-04-13)
  67. * @param time 时间(考试时间,必须使用‘-’隔开 example: 18:00-20:00)
  68. * @return 开始时间和结束时间键值对(" startTime " : 1618308000000, " endTime " : 1618315200000)
  69. */
  70. public static Map<String, Object> analyzeStartAndEndTime(String date, String time) {
  71. time = time.replaceAll(" ", ""); // 去掉所有空格
  72. String[] arr = time.split("-");
  73. if (arr.length != 2) {
  74. // 不能使用'-'拆分成两个时间的报错
  75. throw ExceptionResultEnum.ERROR.exception("提供的时间格式异常 【考试时间】:" + time + " 应该使用如下的格式【考试时间】:18:00-20:00");
  76. }
  77. String startTimeStr = date + " " + arr[0];
  78. String endTimeStr = date + " " + arr[1];
  79. if (Objects.isNull(DateDisposeUtils.parseDate(startTimeStr)) || Objects.isNull(DateDisposeUtils.parseDate(endTimeStr))) {
  80. throw ExceptionResultEnum.ERROR.exception("提供的日期时间格式异常 \n【考试日期】:" + date + " 应该使用如下的格式【考试日期】:2021-09-01 或 2021/09/01 或 2021.09.01" + "\n【考试时间】:" + time + " 应该使用如下的格式【考试时间】:18:00-20:00");
  81. }
  82. long startTime = DateDisposeUtils.parseDate(startTimeStr).getTime();
  83. long endTime = DateDisposeUtils.parseDate(endTimeStr).getTime();
  84. if (startTime >= endTime) {
  85. throw ExceptionResultEnum.ERROR.exception("开始时间要小于结束时间 时间: " + time);
  86. }
  87. Map<String, Object> timeMap = new HashMap<>();
  88. timeMap.put("startTime", startTime);
  89. timeMap.put("endTime", endTime);
  90. return timeMap;
  91. }
  92. /**
  93. * 根据开始时间和结束时间解析日期和时间
  94. *
  95. * @param startTime 开始时间
  96. * @param endTime 结束时间
  97. * @return 键值对
  98. */
  99. public static Map<String, Object> analyzeDateAndTime(Long startTime, Long endTime) {
  100. String tmpDateStart;
  101. String tmpDateEnd;
  102. String tmpTimeStart;
  103. String tmpTimeEnd;
  104. String date;
  105. String time;
  106. Map<String, Object> map = new HashMap<>();
  107. Calendar calendar = Calendar.getInstance();
  108. calendar.setTime(new Date(startTime));
  109. tmpDateStart = (new SimpleDateFormat("yyyy-MM-dd")).format(calendar.getTime());
  110. tmpTimeStart = (new SimpleDateFormat("HH:mm:ss")).format(calendar.getTime());
  111. calendar.setTime(new Date(endTime));
  112. tmpDateEnd = (new SimpleDateFormat("yyyy-MM-dd")).format(calendar.getTime());
  113. tmpTimeEnd = (new SimpleDateFormat("HH:mm:ss")).format(calendar.getTime());
  114. if (!tmpDateStart.equals(tmpDateEnd)) {
  115. throw ExceptionResultEnum.ERROR.exception("开始时间和结束时间不在同一天");
  116. }
  117. date = tmpDateStart;
  118. time = tmpTimeStart + " - " + tmpTimeEnd;
  119. map.put("date", date);
  120. map.put("time", time);
  121. return map;
  122. }
  123. /**
  124. * 根据开始时间和结束时间解析日期和时间
  125. *
  126. * @param startTime 开始时间
  127. * @param endTime 结束时间
  128. */
  129. public static void analyzeAndCompareDateAndTime(Long startTime, Long endTime) {
  130. String tmpDateStart;
  131. String tmpDateEnd;
  132. Calendar calendar = Calendar.getInstance();
  133. calendar.setTime(new Date(startTime));
  134. tmpDateStart = (new SimpleDateFormat("yyyy-MM-dd")).format(calendar.getTime());
  135. calendar.setTime(new Date(endTime));
  136. tmpDateEnd = (new SimpleDateFormat("yyyy-MM-dd")).format(calendar.getTime());
  137. if (!tmpDateStart.equals(tmpDateEnd)) {
  138. throw ExceptionResultEnum.ERROR.exception("开始时间和结束时间不在同一天");
  139. }
  140. if (startTime >= endTime) {
  141. throw ExceptionResultEnum.ERROR.exception("开始时间必须小于结束时间");
  142. }
  143. }
  144. /**
  145. * 获取递增序列号
  146. *
  147. * @param prefix 前缀
  148. * @param model 模块
  149. * @param digit 补齐位数
  150. * @return 序列号
  151. */
  152. public String getIncre(String prefix, String model, int digit) {
  153. StringBuilder temp = new StringBuilder();
  154. for (int i = 0; i < digit; i++) {
  155. temp.append("0");
  156. }
  157. //序列号前缀加特定标识,如系统模块名之类的 防止重复
  158. String key = model + prefix;
  159. String increResult = "";
  160. try {
  161. //如果该key不存在 会自动创建,值为第二个参数delta
  162. //最终调用的还是jedis的incrBy(byte[] key, long value)方法
  163. RedisAtomicLong counter = new RedisAtomicLong(key, Objects.requireNonNull(redisTemplate.getConnectionFactory()));
  164. Long increment = counter.incrementAndGet();
  165. //不足补位
  166. DecimalFormat df = new DecimalFormat(temp.toString());
  167. increResult = prefix + df.format(increment);
  168. } catch (Exception e) {
  169. // TODO: 2021/4/16
  170. System.out.println("获取序列号失败");
  171. /*这里可以根据需求手动生成一个不重复的单号,
  172. * */
  173. }
  174. return increResult;
  175. }
  176. /**
  177. * 解析excel单元格类型
  178. *
  179. * @param cell 单元格
  180. * @return 转换成字符串后的值
  181. */
  182. public static String analyzeExcelCellValue(Cell cell) {
  183. String cellValue;
  184. CellType cellType = cell.getCellTypeEnum();
  185. switch (cellType) {
  186. case NUMERIC:
  187. if (HSSFDateUtil.isCellDateFormatted(cell)) {
  188. SimpleDateFormat sdf;
  189. // 验证short值
  190. if (cell.getCellStyle().getDataFormat() == 14) {
  191. sdf = new SimpleDateFormat("yyyy/MM/dd");
  192. } else if (cell.getCellStyle().getDataFormat() == 21) {
  193. sdf = new SimpleDateFormat("HH:mm:ss");
  194. } else if (cell.getCellStyle().getDataFormat() == 22) {
  195. sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
  196. } else {
  197. throw new RuntimeException("日期格式错误!!!");
  198. }
  199. Date date = cell.getDateCellValue();
  200. cellValue = sdf.format(date);
  201. } else {//处理数值格式
  202. cell.setCellType(CellType.STRING);
  203. cellValue = String.valueOf(cell.getRichStringCellValue().getString());
  204. }
  205. break;
  206. case STRING:
  207. cellValue = String.valueOf(cell.getStringCellValue());
  208. break;
  209. case BOOLEAN:
  210. cellValue = String.valueOf(cell.getBooleanCellValue());
  211. break;
  212. case FORMULA:
  213. cellValue = String.valueOf(cell.getCellFormula());
  214. break;
  215. case BLANK:
  216. cellValue = null;
  217. break;
  218. case ERROR:
  219. cellValue = "非法字符";
  220. break;
  221. default:
  222. cellValue = "未知类型";
  223. break;
  224. }
  225. return cellValue;
  226. }
  227. public static void delFolder(String folderPath) {
  228. try {
  229. delAllFile(folderPath); //删除完里面所有内容
  230. String filePath = folderPath;
  231. filePath = filePath.toString();
  232. File myFilePath = new File(filePath);
  233. myFilePath.delete(); //删除空文件夹
  234. } catch (Exception e) {
  235. log.error(SystemConstant.LOG_ERROR, e);
  236. }
  237. }
  238. public static void delAllFile(String path) {
  239. boolean flag = false;
  240. File file = new File(path);
  241. if (!file.exists()) {
  242. return;
  243. }
  244. if (!file.isDirectory()) {
  245. return;
  246. }
  247. String[] tempList = file.list();
  248. File temp = null;
  249. for (int i = 0; i < Objects.requireNonNull(tempList).length; i++) {
  250. if (path.endsWith(File.separator)) {
  251. temp = new File(path + tempList[i]);
  252. } else {
  253. temp = new File(path + File.separator + tempList[i]);
  254. }
  255. if (temp.isFile()) {
  256. temp.delete();
  257. }
  258. if (temp.isDirectory()) {
  259. delAllFile(path + "/" + tempList[i]);//先删除文件夹里面的文件
  260. delFolder(path + "/" + tempList[i]);//再删除空文件夹
  261. flag = true;
  262. }
  263. }
  264. }
  265. public File saveLocal(InputStream inputStream, String dirPath) throws IOException {
  266. File desFile = new File(dirPath);
  267. if (!desFile.getParentFile().exists()) {
  268. desFile.getParentFile().mkdirs(); //目标文件目录不存在的话需要创建目录
  269. }
  270. byte[] bytes = new byte[1024]; // 开辟一个拷贝缓冲区
  271. OutputStream outputStream = null;
  272. try {
  273. outputStream = new FileOutputStream(desFile);
  274. int length;
  275. while ((length = inputStream.read(bytes)) != -1) { //当读到尽头后,返回值为-1这个时候停止输出,拷贝结束
  276. outputStream.write(bytes, 0, length);
  277. }
  278. return desFile;
  279. } catch (Exception e) {
  280. throw e;
  281. } finally {
  282. if (inputStream != null) {
  283. inputStream.close();
  284. }
  285. if (outputStream != null) {
  286. outputStream.close();
  287. }
  288. }
  289. }
  290. /**
  291. * 判断里面参数只要有一个为空 就是true 全部不为空时 false
  292. *
  293. * @param strArr 字符串组
  294. * @return 全部有值 - false;任意一个为空 - true
  295. */
  296. public static boolean strAnyEmpty(String... strArr) {
  297. if (strArr.length == 0) {
  298. return true;
  299. } else {
  300. for (String str : strArr) {
  301. if (!SystemConstant.strNotNull(str)) {
  302. return true;
  303. }
  304. }
  305. return false;
  306. }
  307. }
  308. public static void outputFile(HttpServletResponse response, InputStream inputStream, String fileName) {
  309. try {
  310. byte[] buf = new byte[1024];
  311. int len = 0;
  312. String fName = new String(fileName.getBytes(), "ISO-8859-1");
  313. response.reset();
  314. response.setContentType("application/x-msdownload");
  315. response.setHeader("Content-Disposition", "attachment; filename=" + fName);
  316. OutputStream outStream = response.getOutputStream();
  317. while ((len = inputStream.read(buf)) > 0) {
  318. outStream.write(buf, 0, len);
  319. }
  320. inputStream.close();
  321. outStream.close();
  322. } catch (IOException e) {
  323. log.error(SystemConstant.LOG_ERROR, e);
  324. }
  325. }
  326. public static void outputFile(HttpServletResponse response, ByteArrayOutputStream baos, String fileName) throws Exception {
  327. try {
  328. String fName = URLEncoder.encode(fileName, SystemConstant.CHARSET_NAME);
  329. response.reset();
  330. response.setContentType("application/x-msdownload");
  331. response.setHeader("Content-Disposition", "attachment; filename=" + fName);
  332. OutputStream outStream = response.getOutputStream();
  333. baos.writeTo(outStream);
  334. outStream.close();
  335. } catch (IOException e) {
  336. throw new Exception("下载失败");
  337. }
  338. }
  339. public static List<File> pdfToImageFile(String sourcePath, String targetPath) throws Exception {
  340. PDDocument doc = null;
  341. ByteArrayOutputStream os = null;
  342. InputStream stream = null;
  343. OutputStream out = null;
  344. List<File> fileList = new ArrayList<>();
  345. try {
  346. // pdf路径
  347. stream = new FileInputStream(sourcePath);
  348. // 加载解析PDF文件
  349. doc = PDDocument.load(stream);
  350. PDFRenderer pdfRenderer = new PDFRenderer(doc);
  351. PDPageTree pages = doc.getPages();
  352. int pageCount = pages.getCount();
  353. for (int i = 0; i < pageCount; i++) {
  354. BufferedImage bim = pdfRenderer.renderImageWithDPI(i, 200);
  355. os = new ByteArrayOutputStream();
  356. ImageIO.write(bim, "jpg", os);
  357. byte[] dataList = os.toByteArray();
  358. // jpg文件转出路径
  359. File file = new File(targetPath + "-" + (i + 1) + SystemConstant.JPG_PREFIX);
  360. if (!file.getParentFile().exists()) {
  361. // 不存在则创建父目录及子文件
  362. file.getParentFile().mkdirs();
  363. file.createNewFile();
  364. }
  365. out = new FileOutputStream(file);
  366. out.write(dataList);
  367. fileList.add(file);
  368. }
  369. } catch (Exception e) {
  370. e.printStackTrace();
  371. throw e;
  372. } finally {
  373. if (doc != null) {
  374. doc.close();
  375. }
  376. if (os != null) {
  377. os.close();
  378. }
  379. if (stream != null) {
  380. stream.close();
  381. }
  382. if (out != null) {
  383. out.close();
  384. }
  385. }
  386. return fileList;
  387. }
  388. public String randomNumberPrefix(String examShortCode, String courseShortCode, String clazzShortCode, Integer examNumberDigit) {
  389. if (examNumberDigit < 7) {
  390. return "";
  391. } else if (examNumberDigit < 11) {
  392. return examShortCode;
  393. } else if (examNumberDigit < 13) {
  394. return examShortCode + courseShortCode;
  395. }
  396. return examShortCode + courseShortCode + clazzShortCode;
  397. }
  398. }