WpsController.java 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. package com.yingpaipay.business.controller;
  2. import com.yingpaipay.business.domain.Document;
  3. import com.yingpaipay.business.domain.dto.WpsGetVersionsDto;
  4. import com.yingpaipay.business.domain.dto.WpsR;
  5. import com.yingpaipay.business.domain.dto.WpsVersionControlDto;
  6. import com.yingpaipay.business.domain.dto.WpsVersionDto;
  7. import com.yingpaipay.business.service.impl.CommonDocumentService;
  8. import jakarta.servlet.http.HttpServletRequest;
  9. import lombok.RequiredArgsConstructor;
  10. import lombok.extern.slf4j.Slf4j;
  11. import org.dromara.common.core.domain.R;
  12. import org.dromara.common.core.exception.BusinessException;
  13. import org.dromara.common.core.utils.StringUtils;
  14. import org.dromara.common.json.utils.JsonUtils;
  15. import org.dromara.common.oss.core.OssClient;
  16. import org.dromara.common.oss.entity.UploadResult;
  17. import org.dromara.common.oss.factory.OssFactory;
  18. import org.dromara.common.web.core.BaseController;
  19. import org.dromara.system.domain.SysOssExt;
  20. import org.dromara.system.domain.SysUser;
  21. import org.dromara.system.domain.vo.SysOssVo;
  22. import org.dromara.system.domain.vo.SysUserVo;
  23. import org.dromara.system.service.ISysOssService;
  24. import org.dromara.system.service.ISysUserService;
  25. import org.springframework.http.MediaType;
  26. import org.springframework.web.bind.annotation.*;
  27. import java.io.File;
  28. import java.io.FileOutputStream;
  29. import java.io.IOException;
  30. import java.io.InputStream;
  31. import java.util.*;
  32. import java.util.concurrent.ConcurrentHashMap;
  33. /**
  34. * @Author: Huanyi
  35. * @Description: 由于 WPS 服务对于版本管理非常的麻烦,版本回退一直没有很好的解决方案,因此直接由我们自己负责管理版本。
  36. */
  37. @Deprecated
  38. @RestController
  39. @RequestMapping("/wps/callback/v3/3rd")
  40. @RequiredArgsConstructor
  41. @Slf4j
  42. public class WpsController extends BaseController {
  43. /**
  44. * 这里为版本控制缓存
  45. */
  46. private static final Map<Long, WpsVersionControlDto> DOCUMENT_MAP = new ConcurrentHashMap<>();
  47. private final ISysOssService ossService;
  48. private final CommonDocumentService documentService;
  49. private final ISysUserService userService;
  50. @PutMapping(value = "/upload/file/{documentId}", consumes = MediaType.APPLICATION_OCTET_STREAM_VALUE)
  51. public void upload(@PathVariable String documentId, HttpServletRequest request) {
  52. String[] ids = documentId.split("_");
  53. WpsVersionControlDto dto = DOCUMENT_MAP.get(Long.valueOf(ids[0]));
  54. File tempFile = null;
  55. try {
  56. tempFile = File.createTempFile(dto.getFileName() + "_", dto.getSuffix());
  57. try (InputStream in = request.getInputStream();
  58. FileOutputStream out = new FileOutputStream(tempFile)) {
  59. byte[] buffer = new byte[8192];
  60. int bytesRead;
  61. while ((bytesRead = in.read(buffer)) != -1) {
  62. out.write(buffer, 0, bytesRead);
  63. }
  64. }
  65. // TODO 防止自增ID过早炸掉,这里采用更新操作,不使用自带的图片上传
  66. String originalfileName = tempFile.getName();
  67. String suffix = StringUtils.substring(originalfileName, originalfileName.lastIndexOf("."));
  68. OssClient storage = OssFactory.instance();
  69. UploadResult uploadResult = storage.uploadSuffix(tempFile, suffix, originalfileName);
  70. dto.setCurrentVersion(Long.parseLong(ids[1]));
  71. List<WpsVersionDto> versions = dto.getVersions();
  72. for (WpsVersionDto version : versions) {
  73. if (Objects.equals(version.getVersion(), Long.valueOf(ids[1]))) {
  74. // FIXME 由于原始版本不能被删除,暂时先不实现: 每新增一个版本,就将原始版本上传一个全新的版本
  75. // // TODO 旧的版本可以不需要了,只需要新的版本
  76. // storage.delete(version.getUrl());
  77. version.setFileName(uploadResult.getFilename());
  78. version.setUrl(uploadResult.getUrl());
  79. version.setUpdateTime(new Date());
  80. }
  81. }
  82. } catch (IOException e) {
  83. log.error("文件写入失败, documentId={}", documentId, e);
  84. } finally {
  85. if (tempFile != null && tempFile.exists()) {
  86. boolean deleted = tempFile.delete();
  87. if (!deleted) {
  88. log.warn("临时文件删除失败: {}", tempFile.getAbsolutePath());
  89. }
  90. }
  91. }
  92. }
  93. private record WpsFilesCompleteRequestDto(
  94. String file_id, Object request, String name, Integer size, Map<String, String> digest, Boolean is_manual, Object response, Integer status_code
  95. ) {}
  96. private record WpsFilesCompleteResponseDto(
  97. String id, String name, Integer version, Integer size, Integer create_time, Integer modify_time, String creator_id, String modifier_id
  98. ) {}
  99. @PostMapping("/files/{documentId}/upload/complete")
  100. public WpsR complete(@PathVariable String documentId, @RequestBody WpsFilesCompleteRequestDto dto) {
  101. Map<String, Object> request = (LinkedHashMap<String, Object>) dto.request;
  102. return WpsR.ok(
  103. new WpsFilesCompleteResponseDto(
  104. String.valueOf(request.get("file_id")), String.valueOf(request.get("name")), 1, Integer.valueOf(String.valueOf(request.get("size"))), Math.toIntExact(System.currentTimeMillis() / 1000L), Math.toIntExact(System.currentTimeMillis() / 1000L), "1", "1"
  105. )
  106. );
  107. }
  108. private record WpsUplaodPrepareDto(String[] digest_types) {}
  109. @GetMapping("/files/{documentId}/upload/prepare")
  110. public WpsR<WpsUplaodPrepareDto> uploadPrepare(@PathVariable String documentId) {
  111. String[] types = {"md5"};
  112. return WpsR.ok(new WpsUplaodPrepareDto(types));
  113. }
  114. private record WpsUploadAddressRequestDto(
  115. String file_id, String name, Integer size, Map<String, String> digest, Boolean is_manual, Integer attachment_size, String content_type
  116. ) {}
  117. private record WpsUploadAddressResponseDto(String method, String url) {}
  118. @PostMapping("/files/{documentId}/upload/address")
  119. public WpsR uploadAddress(@PathVariable String documentId, @RequestBody WpsUploadAddressRequestDto dto) {
  120. return WpsR.ok(new WpsUploadAddressResponseDto("PUT", "http://yp1.yingpaipay.com:9029/wps/callback/v3/3rd/upload/file/" + documentId));
  121. }
  122. private record WpsGetFileInfoDto(
  123. String id, String name, Integer version, Integer size, Integer create_time, Integer modify_time, String creator_id, String modifier_id
  124. ) {}
  125. @GetMapping("/files/{documentId}")
  126. public WpsR<WpsGetFileInfoDto> getFileInfo(@PathVariable String documentId) {
  127. String[] ids = documentId.split("_");
  128. long id = Long.parseLong(ids[0]);
  129. long version = Long.parseLong(ids[1]);
  130. if (DOCUMENT_MAP.containsKey(id)) {
  131. WpsVersionControlDto dto = DOCUMENT_MAP.get(id);
  132. return WpsR.ok(new WpsGetFileInfoDto(
  133. documentId, dto.getFileName(), 1, dto.getSize(), Math.toIntExact(new Date().getTime() / 1000L), Math.toIntExact(new Date().getTime() / 1000L), dto.getCreator(), dto.getUpdator()
  134. ));
  135. }
  136. WpsVersionControlDto dto = initDocument(id);
  137. return WpsR.ok(new WpsGetFileInfoDto(
  138. documentId, dto.getFileName(), 1, dto.getSize(), Math.toIntExact(new Date().getTime() / 1000L), Math.toIntExact(new Date().getTime() / 1000L), dto.getCreator(), dto.getUpdator()
  139. ));
  140. }
  141. private record WpsFilesPermissionDto(
  142. String user_id, Integer read, Integer update, Integer download, Integer rename, Integer history, Integer copy, Integer print, Integer saves, Integer comment
  143. ) {}
  144. /**
  145. * 随便写的,没必要划分的这么细致
  146. */
  147. @GetMapping("/files/{documentId}/permission")
  148. public WpsR permission(@PathVariable String documentId) {
  149. return WpsR.ok(
  150. new WpsFilesPermissionDto(
  151. "1", 1, 1, 1, 1, 1, 1, 1, 1, 1
  152. )
  153. );
  154. }
  155. private record WpsGetUrlDto(String url) {}
  156. @GetMapping("/files/{documentId}/download")
  157. public WpsR getUrl(@PathVariable String documentId) {
  158. String[] ids = documentId.split("_");
  159. long id = Long.parseLong(ids[0]);
  160. long version = Long.parseLong(ids[1]);
  161. if (DOCUMENT_MAP.containsKey(id)) {
  162. WpsVersionControlDto dto = DOCUMENT_MAP.get(id);
  163. List<WpsVersionDto> versions = dto.getVersions();
  164. for (WpsVersionDto versionDto : versions) {
  165. if (versionDto.getVersion() == version) {
  166. return WpsR.ok(new WpsGetUrlDto(versionDto.getUrl()));
  167. }
  168. }
  169. return WpsR.ok(new WpsGetUrlDto(dto.getVersions().get(0).getUrl()));
  170. }
  171. WpsVersionControlDto dto = initDocument(id);
  172. List<WpsVersionDto> versions = dto.getVersions();
  173. for (WpsVersionDto versionDto : versions) {
  174. if (Objects.equals(versionDto.getVersion(), dto.getCurrentVersion())) {
  175. return WpsR.ok(new WpsGetUrlDto(versionDto.getUrl()));
  176. }
  177. }
  178. return WpsR.ok(new WpsGetUrlDto(dto.getVersions().get(0).getUrl()));
  179. }
  180. @GetMapping("/files/{documentId}/versions/{version}/download")
  181. public WpsR getUrlByVersion(@PathVariable String documentId, @PathVariable Integer version) {
  182. if (DOCUMENT_MAP.containsKey(Long.valueOf(documentId.split("_")[0]))) {
  183. WpsVersionControlDto dto = DOCUMENT_MAP.get(Long.valueOf(documentId.split("_")[0]));
  184. return WpsR.ok(new WpsGetUrlDto(dto.getVersions().get(Integer.parseInt(documentId.split("_")[1])).getUrl()));
  185. }
  186. WpsVersionControlDto dto = initDocument(Long.valueOf(documentId.split("_")[0]));
  187. return WpsR.ok(new WpsGetUrlDto(dto.getVersions().get(0).getUrl()));
  188. }
  189. private record WpsGetUsersDto(String id, String name, String avatar_url) {}
  190. @GetMapping("/users")
  191. public WpsR getUsers(@RequestParam("user_ids") Long[] userIds) {
  192. if (userIds == null || userIds.length == 0) {
  193. return WpsR.ok();
  194. }
  195. List<SysUser> vos = userService.selectUserByIds(Arrays.stream(userIds).toList());
  196. List<Long> ossIds = new ArrayList<>();
  197. vos.forEach(e -> ossIds.add(e.getAvatar()));
  198. List<SysOssVo> ossVos = ossService.queryListByIds(ossIds);
  199. List<WpsGetUsersDto> dtos = new ArrayList<>();
  200. for (SysUser vo : vos) {
  201. String url = "";
  202. for (SysOssVo ossVo : ossVos) {
  203. if (ossVo.getOssId().equals(vo.getAvatar())) {
  204. url = ossVo.getUrl();
  205. }
  206. }
  207. dtos.add(new WpsGetUsersDto(String.valueOf(vo.getUserId()), vo.getNickName(), url));
  208. }
  209. return WpsR.ok(dtos);
  210. }
  211. @PostMapping(value = "/init/{documentId}")
  212. public R init(@PathVariable Long documentId) {
  213. if (DOCUMENT_MAP.containsKey(documentId)) {
  214. throw new BusinessException("已有其他人正在审核该文件");
  215. }
  216. initDocument(documentId);
  217. return R.ok(DOCUMENT_MAP.get(documentId).getCurrentVersion());
  218. }
  219. private WpsVersionControlDto initDocument(Long ossId) {
  220. SysOssVo ossVo = ossService.getById(ossId);
  221. Document document = documentService.getByOssId(ossId);
  222. if (DOCUMENT_MAP.containsKey(document.getId())) {
  223. throw new BusinessException("已有其他人正在审核该文件");
  224. }
  225. long currentVersion = System.currentTimeMillis();
  226. List<WpsVersionDto> list = new ArrayList<>();
  227. list.add(new WpsVersionDto(ossVo.getFileName(), 0L, ossVo.getUrl(), new Date(), new Date(), Math.toIntExact(document.getCreateTime().getTime() / 1000L), Math.toIntExact(document.getUpdateTime().getTime() / 1000L)));
  228. list.add(new WpsVersionDto(ossVo.getFileName(), currentVersion, ossVo.getUrl(), new Date(), new Date(), Math.toIntExact(document.getCreateTime().getTime() / 1000L), Math.toIntExact(document.getUpdateTime().getTime() / 1000L)));
  229. WpsVersionControlDto dto = new WpsVersionControlDto();
  230. dto.setCurrentVersion(currentVersion);
  231. dto.setVersions(list);
  232. dto.setSuffix(ossVo.getFileSuffix());
  233. dto.setCreator(String.valueOf(document.getCreateBy()));
  234. dto.setUpdator(String.valueOf(document.getUpdateBy()));
  235. dto.setFileName(ossVo.getOriginalName());
  236. SysOssExt ext = JsonUtils.parseObject(ossVo.getExt1(), SysOssExt.class);
  237. long size = ext.getFileSize();
  238. dto.setSize((int) size);
  239. DOCUMENT_MAP.put(ossId, dto);
  240. return dto;
  241. }
  242. @PutMapping("/clean/{documentId}")
  243. public R clean(@PathVariable Long documentId) {
  244. WpsVersionControlDto dto = DOCUMENT_MAP.get(documentId);
  245. long currentVersion = System.currentTimeMillis();
  246. dto.getVersions().add(new WpsVersionDto(
  247. dto.getVersions().get(0).getFileName(), currentVersion, dto.getVersions().get(0).getUrl(), new Date(), new Date(), Math.toIntExact(new Date().getTime() / 1000L), Math.toIntExact(new Date().getTime() / 1000L)
  248. ));
  249. dto.setCurrentVersion(currentVersion);
  250. log.info("自行进行刷新版本");
  251. dto.getVersions().forEach(e -> log.info("{}", JsonUtils.toJsonString(e)));
  252. return R.ok(currentVersion);
  253. }
  254. /**
  255. * 已废弃
  256. */
  257. @GetMapping("/files/{documentId}/versions")
  258. public WpsR getVersions(@PathVariable Long documentId, @RequestParam(value = "offset", required = false) Integer offset, @RequestParam(value = "limit", required = false) Integer size) {
  259. WpsVersionControlDto dto = DOCUMENT_MAP.get(documentId);
  260. List<WpsVersionDto> versions = dto.getVersions();
  261. List<WpsVersionDto> reversed = new ArrayList<>(versions);
  262. Collections.reverse(reversed);
  263. if (offset == null || size == null) {
  264. return WpsR.ok(reversed);
  265. }
  266. int fromIndex = Math.min(offset, reversed.size());
  267. int toIndex = Math.min(offset + size, reversed.size());
  268. List<WpsVersionDto> paginated = reversed.subList(fromIndex, toIndex);
  269. List<WpsGetVersionsDto> list = new ArrayList<>();
  270. paginated.forEach(e -> list.add(new WpsGetVersionsDto(
  271. String.valueOf(documentId), dto.getFileName(), Math.toIntExact(e.getVersion() / 1000L), dto.getSize(), e.getCreate_time(), e.getUpdate_time(), dto.getCreator(), dto.getUpdator()
  272. )));
  273. WpsR<List<WpsGetVersionsDto>> r = WpsR.ok(list);
  274. String str = JsonUtils.toJsonString(r);
  275. log.warn(str);
  276. return r;
  277. }
  278. /**
  279. * 已废弃
  280. */
  281. @GetMapping("/files/{documentId}/versions/{version}")
  282. public WpsR getFileByVersion(@PathVariable Long documentId, @PathVariable Integer version) {
  283. WpsVersionControlDto dto = DOCUMENT_MAP.get(documentId);
  284. WpsVersionDto current = dto.getVersions().get(version - 1);
  285. return WpsR.ok(new WpsGetVersionsDto(
  286. String.valueOf(documentId), dto.getFileName(), Math.toIntExact(current.getVersion() / 1000L), dto.getSize(), current.getCreate_time(), current.getUpdate_time(), dto.getCreator(), dto.getUpdator()
  287. ));
  288. }
  289. @GetMapping("/files/list")
  290. public R<List<WpsVersionDto>> getVersionList(@RequestParam("ossId") Long ossId) {
  291. List<WpsVersionDto> list = DOCUMENT_MAP.get(ossId).getVersions();
  292. list.forEach(e -> log.info("{}", JsonUtils.toJsonString(e)));
  293. return R.ok(list.stream().filter(e -> e.getVersion() != 0L).sorted((e1, e2) -> Math.toIntExact(e2.getVersion() - e1.getVersion())).toList());
  294. }
  295. @GetMapping("/getFinal")
  296. public R<SysOssVo> getFinal(@RequestParam("id") String id) {
  297. String[] ids = id.split("_");
  298. long documentId = Long.parseLong(ids[0]);
  299. long version = Long.parseLong(ids[1]);
  300. log.info("文档编号为 {}, 版本号为 : {}", documentId, version);
  301. WpsVersionControlDto dto = DOCUMENT_MAP.get(documentId);
  302. List<WpsVersionDto> versions = dto.getVersions();
  303. for (WpsVersionDto versionDto : versions) {
  304. log.info("当前轮询的版本号为 {}", versionDto.getVersion());
  305. if (versionDto.getVersion() == version) {
  306. String url = versionDto.getUrl();
  307. SysOssVo vo = ossService.insertByUrl(versionDto.getFileName(), dto.getFileName(), url);
  308. DOCUMENT_MAP.remove(documentId);
  309. return R.ok(vo);
  310. }
  311. }
  312. throw new BusinessException("审核内容保存失败");
  313. }
  314. @DeleteMapping("/cancel/{documentId}")
  315. public R<Void> cancel(@PathVariable Long documentId) {
  316. DOCUMENT_MAP.remove(documentId);
  317. return R.ok();
  318. }
  319. }