UtilsController.java 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482
  1. package jnpf.controller;
  2. import com.alibaba.fastjson.JSONObject;
  3. import io.swagger.v3.oas.annotations.Operation;
  4. import io.swagger.v3.oas.annotations.Parameter;
  5. import io.swagger.v3.oas.annotations.Parameters;
  6. import io.swagger.v3.oas.annotations.tags.Tag;
  7. import jakarta.servlet.http.HttpServletRequest;
  8. import jakarta.servlet.http.HttpServletResponse;
  9. import jnpf.base.ActionResult;
  10. import jnpf.base.UserInfo;
  11. import jnpf.base.entity.DictionaryDataEntity;
  12. import jnpf.base.service.DictionaryDataService;
  13. import jnpf.base.util.OptimizeUtil;
  14. import jnpf.base.vo.DownloadVO;
  15. import jnpf.base.vo.ListVO;
  16. import jnpf.config.ConfigValueUtil;
  17. import jnpf.constant.FileTypeConstant;
  18. import jnpf.constant.MsgCode;
  19. import jnpf.consts.DeviceType;
  20. import jnpf.entity.FileDetail;
  21. import jnpf.entity.FileParameter;
  22. import jnpf.exception.DataException;
  23. import jnpf.model.*;
  24. import jnpf.service.FileService;
  25. import jnpf.util.*;
  26. import jnpf.utils.YozoUtils;
  27. import lombok.Cleanup;
  28. import lombok.extern.slf4j.Slf4j;
  29. import org.apache.commons.codec.binary.Base64;
  30. import org.apache.commons.io.FileUtils;
  31. import org.dromara.x.file.storage.core.FileInfo;
  32. import org.springframework.beans.factory.annotation.Autowired;
  33. import org.springframework.http.MediaType;
  34. import org.springframework.web.bind.annotation.*;
  35. import org.springframework.web.multipart.MultipartFile;
  36. import java.io.*;
  37. import java.nio.channels.Channels;
  38. import java.nio.channels.FileChannel;
  39. import java.nio.channels.WritableByteChannel;
  40. import java.nio.file.Files;
  41. import java.nio.file.Paths;
  42. import java.time.LocalDate;
  43. import java.time.format.DateTimeFormatter;
  44. import java.util.*;
  45. import java.util.stream.Collectors;
  46. /**
  47. * 通用控制器
  48. *
  49. * @author JNPF开发平台组
  50. * @version V1.2.191207
  51. * @copyright 引迈信息技术有限公司
  52. * @date 2019年9月26日 上午9:18
  53. */
  54. @Slf4j
  55. @Tag(name = "公共", description = "file")
  56. @RestController
  57. @RequestMapping("/api/file")
  58. public class UtilsController {
  59. @Autowired
  60. private ConfigValueUtil configValueUtil;
  61. @Autowired
  62. private RedisUtil redisUtil;
  63. @Autowired
  64. private DictionaryDataService dictionaryDataService;
  65. @Autowired
  66. private FileService fileService;
  67. /**
  68. * 语言列表
  69. *
  70. * @return
  71. */
  72. // @Operation(summary = "语言列表")
  73. // @GetMapping("/Language")
  74. // public ActionResult<ListVO<LanguageVO>> getList() {
  75. // String dictionaryTypeId = "dc6b2542d94b407cac61ec1d59592901";
  76. // List<DictionaryDataEntity> list = dictionaryDataService.getList(dictionaryTypeId);
  77. // List<LanguageVO> language = JsonUtil.getJsonToList(list, LanguageVO.class);
  78. // ListVO vo = new ListVO();
  79. // vo.setList(language);
  80. // return ActionResult.success(vo);
  81. // }
  82. /**
  83. * 图形验证码
  84. *
  85. * @return
  86. */
  87. @NoDataSourceBind()
  88. @Operation(summary = "图形验证码")
  89. @GetMapping("/ImageCode/{timestamp}")
  90. @Parameters({
  91. @Parameter(name = "timestamp", description = "时间戳", required = true),
  92. })
  93. public void imageCode(@PathVariable("timestamp") String timestamp) {
  94. DownUtil.downCode(null);
  95. redisUtil.insert(timestamp, ServletUtil.getSession().getAttribute(CodeUtil.RANDOMCODEKEY), 120);
  96. }
  97. /**
  98. * 获取全部下载文件链接(打包下载)
  99. *
  100. * @return
  101. */
  102. @NoDataSourceBind
  103. @Operation(summary = "获取全部下载文件链接(打包下载)")
  104. @PostMapping("/PackDownload/{type}")
  105. public ActionResult packDownloadUrl(@PathVariable("type") String type, @RequestBody List<Map<String, String>> fileInfoList) throws Exception {
  106. type = XSSEscape.escape(type);
  107. if (fileInfoList == null || fileInfoList.isEmpty()) {
  108. return ActionResult.fail(MsgCode.FA047.get());
  109. }
  110. String zipTempFilePath = null;
  111. String zipFileId = RandomUtil.uuId() + ".zip";
  112. List<String> repeatName = new ArrayList<>();
  113. for (Map fileInfoMap : fileInfoList) {
  114. String fileId = XSSEscape.escape((String) fileInfoMap.get("fileId")).trim();
  115. String fileName = XSSEscape.escape((String) fileInfoMap.get("fileName")).trim();
  116. if (repeatName.contains(fileName)) {
  117. fileName = fileName.substring(0, fileName.lastIndexOf(".")) + "副本" + UUID.randomUUID().toString().substring(0, 5) + fileName.substring(fileName.lastIndexOf("."));
  118. } else {
  119. repeatName.add(fileName);
  120. }
  121. if (StringUtil.isEmpty(fileId) || StringUtil.isEmpty(fileName)) {
  122. continue;
  123. }
  124. FileParameter fileParameter = new FileParameter(type, fileId);
  125. if (FileUploadUtils.exists(fileParameter)) {
  126. // String typePath = FilePathUtil.getFilePath(type);
  127. // if (fileId.indexOf(",") >= 0) {
  128. // typePath += fileId.substring(0, fileId.lastIndexOf(",") + 1).replaceAll(",", "/");
  129. // fileId = fileId.substring(fileId.lastIndexOf(",") + 1);
  130. // }
  131. if (zipTempFilePath == null) {
  132. zipTempFilePath = FileUploadUtils.getLocalBasePath() + FilePathUtil.getFilePath(FileTypeConstant.FILEZIPDOWNTEMPPATH);
  133. if (!new File(zipTempFilePath).exists()) {
  134. new File(zipTempFilePath).mkdirs();
  135. }
  136. zipTempFilePath += zipFileId;
  137. }
  138. // fileParameter.setRemotePath(typePath);
  139. String finalZipTempFilePath = zipTempFilePath;
  140. String finalFileName = fileName;
  141. FileUploadUtils.downloadFile(fileParameter, inputStream -> {
  142. try {
  143. ZipUtil.fileAddToZip(finalZipTempFilePath, inputStream, finalFileName);
  144. } catch (Exception e) {
  145. throw new RuntimeException(e);
  146. }
  147. });
  148. }
  149. }
  150. if (zipTempFilePath == null) {
  151. return ActionResult.fail(MsgCode.FA018.get());
  152. }
  153. //将文件上传到默认文件服务器
  154. String newFileId = zipFileId;
  155. if (!"local".equals(FileUploadUtils.getDefaultPlatform())) { //不是本地,说明是其他文件服务器,将zip文件上传到其他服务器里,方便下载
  156. File zipFile = new File(zipTempFilePath);
  157. FileInfo fileInfo = FileUploadUtils.uploadFile(new FileParameter(FilePathUtil.getFilePath(FileTypeConstant.FILEZIPDOWNTEMPPATH), zipFileId), zipFile);
  158. zipFile.delete();
  159. newFileId = fileInfo.getFilename();
  160. }
  161. jnpf.base.vo.DownloadVO vo = DownloadVO.builder().name(zipFileId).url(UploaderUtil.uploaderFile(newFileId + "#" + FileTypeConstant.FILEZIPDOWNTEMPPATH)).build();
  162. Map<String, Object> map = new HashMap<String, Object>();
  163. map.put("downloadVo", vo);
  164. map.put("downloadName", "文件" + zipFileId);
  165. return ActionResult.success(map);
  166. }
  167. /**
  168. * 上传文件/图片
  169. *
  170. * @return
  171. */
  172. @NoDataSourceBind()
  173. @Operation(summary = "上传文件/图片")
  174. @PostMapping(value = "/Uploader/{type}", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
  175. @Parameters({
  176. @Parameter(name = "type", description = "类型", required = true)
  177. })
  178. public ActionResult<UploaderVO> uploader(@PathVariable("type") String type, MultipartFile file, MergeChunkDto mergeChunkDto, HttpServletRequest httpServletRequest) {
  179. mergeChunkDto.setType(type);
  180. return ActionResult.success(fileService.uploadFile(mergeChunkDto, file));
  181. }
  182. /**
  183. * 图片转成base64
  184. *
  185. * @return
  186. */
  187. @NoDataSourceBind()
  188. @Operation(summary = "图片转成base64")
  189. @PostMapping(value = "/Uploader/imgToBase64", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
  190. public ActionResult imgToBase64(@RequestParam("file") MultipartFile file) throws IOException {
  191. String encode = cn.hutool.core.codec.Base64.encode(file.getBytes());
  192. Object base64Name = "";
  193. if (StringUtil.isNotEmpty(encode)) {
  194. base64Name = "data:image/jpeg;base64,"+encode;
  195. }
  196. return ActionResult.success(base64Name);
  197. }
  198. /**
  199. * 获取下载文件链接
  200. *
  201. * @return
  202. */
  203. @NoDataSourceBind()
  204. @Operation(summary = "获取下载文件链接")
  205. @GetMapping("/Download/{type}/{fileName}")
  206. @Parameters({
  207. @Parameter(name = "type", description = "类型", required = true),
  208. @Parameter(name = "fileName", description = "文件名称", required = true),
  209. })
  210. public ActionResult downloadUrl(@PathVariable("type") String type, @PathVariable("fileName") String fileName) {
  211. boolean exists = FileUploadUtils.exists(new FileParameter(type, fileName));
  212. if (exists) {
  213. DownloadVO vo = DownloadVO.builder().name(fileName).url(UploaderUtil.uploaderFile(fileName + "#" + type)).build();
  214. return ActionResult.success(vo);
  215. }
  216. return ActionResult.fail(MsgCode.FA018.get());
  217. }
  218. /**
  219. * 下载文件链接
  220. *
  221. * @return
  222. */
  223. @NoDataSourceBind()
  224. @Operation(summary = "下载文件链接")
  225. @GetMapping("/Download")
  226. public void downloadFile(@RequestParam("encryption") String encryption, @RequestParam("name") String downName) throws DataException {
  227. fileService.downloadFile(encryption, downName);
  228. }
  229. /**
  230. * 下载文件链接
  231. *
  232. * @return
  233. */
  234. // @NoDataSourceBind()
  235. // @Operation(summary = "下载模板文件链接")
  236. // @GetMapping("/DownloadModel")
  237. // public void downloadModel() throws DataException {
  238. // HttpServletRequest request = ServletUtil.getRequest();
  239. // String reqJson = request.getParameter("encryption");
  240. // String fileNameAll = DesUtil.aesDecode(reqJson);
  241. // if (!StringUtil.isEmpty(fileNameAll)) {
  242. // String token = fileNameAll.split("#")[0];
  243. // if (TicketUtil.parseTicket(token) != null) {
  244. // TicketUtil.deleteTicket(token);
  245. // String fileName = fileNameAll.split("#")[1];
  246. // String filePath = configValueUtil.getTemplateFilePath();
  247. // // 下载文件
  248. // FileUploadUtils.downloadFile(new FileParameter(filePath, fileName), inputStream -> {
  249. // FileDownloadUtil.outFile(inputStream, fileName);
  250. // });
  251. // } else {
  252. // throw new DataException(MsgCode.FA039.get());
  253. // }
  254. // } else {
  255. // throw new DataException(MsgCode.FA039.get());
  256. // }
  257. // }
  258. /**
  259. * 获取图片
  260. *
  261. * @param fileName
  262. * @param type
  263. * @return
  264. */
  265. @NoDataSourceBind()
  266. @Operation(summary = "获取图片")
  267. @GetMapping("/Image/{type}/{fileName}")
  268. @Parameters({
  269. @Parameter(name = "type", description = "类型", required = true),
  270. @Parameter(name = "fileName", description = "名称", required = true),
  271. })
  272. public void downLoadImg(@PathVariable("type") String type, @PathVariable("fileName") String fileName, @RequestParam(name = "s", required = false) String securityKey, @RequestParam(name = "t", required = false) String t) throws DataException {
  273. fileService.flushFile(type, fileName, securityKey, StringUtil.isEmpty(t));
  274. }
  275. /**
  276. * 获取IM聊天图片
  277. * 注意 后缀名前端故意把 .替换@
  278. *
  279. * @param fileName
  280. * @return
  281. */
  282. // @NoDataSourceBind()
  283. // @Operation(summary = "获取IM聊天图片")
  284. // @GetMapping("/IMImage/{fileName}")
  285. // @Parameters({
  286. // @Parameter(name = "fileName", description = "名称", required = true),
  287. // })
  288. // public void imImage(@PathVariable("fileName") String fileName) {
  289. // FileUploadUtils.downloadFile(new FileParameter(configValueUtil.getImContentFilePath(), fileName), inputStream -> {
  290. // FileDownloadUtil.flushFile(inputStream, fileName);
  291. // });
  292. // }
  293. /**
  294. * 查看图片
  295. *
  296. * @param type 哪个文件夹
  297. * @param fileName 文件名称
  298. * @return
  299. */
  300. // @NoDataSourceBind()
  301. // @Operation(summary = "查看图片")
  302. // @GetMapping("/{type}/{fileName}")
  303. // @Parameters({
  304. // @Parameter(name = "fileName", description = "名称", required = true),
  305. // @Parameter(name = "type", description = "类型", required = true),
  306. // })
  307. // public void img(@PathVariable("type") String type, @PathVariable("fileName") String fileName) {
  308. //// String filePath = configValueUtil.getBiVisualPath() + type + File.separator;
  309. //// if (StorageType.MINIO.equals(configValueUtil.getFileType())) {
  310. //// fileName = "/" + type + "/" + fileName;
  311. //// filePath = configValueUtil.getBiVisualPath().substring(0, configValueUtil.getBiVisualPath().length() - 1);
  312. //// }
  313. // String filePath = FilePathUtil.getFilePath(type.toLowerCase());
  314. // if (fileName.indexOf(",") >= 0) {
  315. // filePath += fileName.substring(0, fileName.lastIndexOf(",") + 1).replaceAll(",", "/");
  316. // fileName = fileName.substring(fileName.lastIndexOf(",") + 1);
  317. // }
  318. // //下载文件
  319. // String finalFileName = fileName;
  320. // FileUploadUtils.downloadFile(new FileParameter(filePath, fileName), inputStream -> {
  321. // FileDownloadUtil.flushFile(inputStream, finalFileName);
  322. // });
  323. // }
  324. /**
  325. * 获取IM聊天语音
  326. * 注意 后缀名前端故意把 .替换@
  327. *
  328. * @param fileName
  329. * @return
  330. */
  331. // @NoDataSourceBind()
  332. // @Operation(summary = "获取IM聊天语音")
  333. // @GetMapping("/IMVoice/{fileName}")
  334. // @Parameters({
  335. // @Parameter(name = "fileName", description = "名称", required = true),
  336. // })
  337. // public void imVoice(@PathVariable("fileName") String fileName) {
  338. // fileName = fileName.replaceAll("@", ".");
  339. // String finalFileName = fileName;
  340. // FileUploadUtils.downloadFile(new FileParameter(configValueUtil.getImContentFilePath(), fileName), inputStream -> {
  341. // FileDownloadUtil.flushFile(inputStream, finalFileName);
  342. // });
  343. // }
  344. /**
  345. * app启动获取信息
  346. *
  347. * @param appName
  348. * @return
  349. */
  350. @NoDataSourceBind()
  351. @Operation(summary = "app启动获取信息")
  352. @GetMapping("/AppStartInfo/{appName}")
  353. @Parameters({
  354. @Parameter(name = "appName", description = "名称", required = true),
  355. })
  356. public ActionResult getAppStartInfo(@PathVariable("appName") String appName) {
  357. appName = XSSEscape.escape(appName);
  358. JSONObject object = new JSONObject();
  359. object.put("AppVersion", configValueUtil.getAppVersion());
  360. object.put("AppUpdateContent", configValueUtil.getAppUpdateContent());
  361. return ActionResult.success(object);
  362. }
  363. //----------大屏图片下载---------
  364. @NoDataSourceBind()
  365. @Operation(summary = "获取图片")
  366. @GetMapping("/VisusalImg/{bivisualpath}/{type}/{fileName}")
  367. @Parameters({
  368. @Parameter(name = "type", description = "类型", required = true),
  369. @Parameter(name = "bivisualpath", description = "路径", required = true),
  370. @Parameter(name = "fileName", description = "名称", required = true),
  371. })
  372. public void downVisusalImg(@PathVariable("type") String type, @PathVariable("bivisualpath") String bivisualpath, @PathVariable("fileName") String fileName) {
  373. fileName = XSSEscape.escape(fileName);
  374. String filePath = configValueUtil.getBiVisualPath();
  375. String finalFileName = fileName;
  376. FileUploadUtils.downloadFile(new FileParameter(filePath + type + "/", fileName), inputStream -> {
  377. FileDownloadUtil.flushFile(inputStream, finalFileName);
  378. });
  379. }
  380. //----------------------
  381. @NoDataSourceBind()
  382. @Operation(summary = "预览文件")
  383. @GetMapping("/Uploader/Preview")
  384. public ActionResult Preview(PreviewParams previewParams) {
  385. return ActionResult.success(MsgCode.SU000.get(), fileService.previewFile(previewParams));
  386. }
  387. // @NoDataSourceBind()
  388. // @Operation(summary = "kk本地文件预览")
  389. // @GetMapping("/filedownload/{type}/{fileName}")
  390. // @Deprecated
  391. // public void filedownload(@PathVariable("type") String type, @PathVariable("fileName") String fileName, HttpServletResponse response) {
  392. // String typePath = FilePathUtil.getFilePath(type);
  393. // if (fileName.indexOf(",") >= 0) {
  394. // typePath += fileName.substring(0, fileName.lastIndexOf(",") + 1).replaceAll(",", "/");
  395. // fileName = fileName.substring(fileName.lastIndexOf(",") + 1);
  396. // }
  397. // String tmpPath = typePath + fileName;
  398. // boolean b = FileUtil.fileIsFile(tmpPath);
  399. // if (!b) {
  400. // FileUploadUtils.downloadFileToLocal(new FileParameter(type, fileName).setLocaFilelPath(FileUploadUtils.getLocalBasePath() + typePath));
  401. // }
  402. // String filePath = XSSEscape.escapePath(FileUploadUtils.getLocalBasePath() + typePath + fileName);
  403. // OutputStream os = null;
  404. // //本地取对应文件
  405. // File file = new File(filePath);
  406. // try {
  407. // os = response.getOutputStream();
  408. // String contentType = Files.probeContentType(Paths.get(file.getAbsolutePath()));
  409. // response.setHeader("Content-Type", contentType);
  410. // response.setHeader("Content-Dispostion", "attachment;filename=" + new String(file.getName().getBytes("utf-8"), "ISO8859-1"));
  411. // @Cleanup FileInputStream fileInputStream = new FileInputStream(file);
  412. //
  413. // @Cleanup WritableByteChannel writableByteChannel = Channels.newChannel(os);
  414. //
  415. // @Cleanup FileChannel channel = fileInputStream.getChannel();
  416. // channel.transferTo(0, channel.size(), writableByteChannel);
  417. // channel.close();
  418. // os.flush();
  419. // writableByteChannel.close();
  420. // } catch (IOException e) {
  421. // e.printStackTrace();
  422. // } finally {
  423. // try {
  424. // if (os != null) {
  425. // os.close();
  426. // }
  427. // } catch (IOException e) {
  428. // e.printStackTrace();
  429. // }
  430. // }
  431. // }
  432. @Operation(summary = "分片上传获取")
  433. @GetMapping("/chunk")
  434. public ActionResult<ChunkRes> checkChunk(Chunk chunk) {
  435. return ActionResult.success(fileService.checkChunk(chunk));
  436. }
  437. @Operation(summary = "分片上传附件")
  438. @PostMapping("/chunk")
  439. public ActionResult<ChunkRes> upload(Chunk chunk, MultipartFile file) {
  440. return ActionResult.success(fileService.uploadChunk(chunk, file));
  441. }
  442. @Operation(summary = "分片组装")
  443. @PostMapping("/merge")
  444. public ActionResult<UploaderVO> merge(MergeChunkDto mergeChunkDto) {
  445. return ActionResult.success(fileService.mergeChunk(mergeChunkDto));
  446. }
  447. public static void main(String[] args) {
  448. String path = "../../../windows/win.ini|userAvatar/../../../../windows/win.ini";
  449. System.out.printf(XSSEscape.escapePath(path));
  450. }
  451. }