FileInfoServiceImpl.java 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. package com.fjhx.file.service.impl;
  2. import cn.hutool.core.bean.BeanUtil;
  3. import cn.hutool.core.date.DateUtil;
  4. import cn.hutool.core.io.FileUtil;
  5. import cn.hutool.core.io.IoUtil;
  6. import cn.hutool.core.util.IdUtil;
  7. import cn.hutool.core.util.ObjectUtil;
  8. import com.baomidou.dynamic.datasource.annotation.DS;
  9. import com.baomidou.mybatisplus.core.toolkit.IdWorker;
  10. import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
  11. import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
  12. import com.baomidou.mybatisplus.core.toolkit.IdWorker;
  13. import com.baomidou.mybatisplus.core.toolkit.Wrappers;
  14. import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
  15. import com.fjhx.file.entity.*;
  16. import com.fjhx.file.mapper.FileInfoMapper;
  17. import com.fjhx.file.service.FileInfoService;
  18. import com.obs.services.ObsClient;
  19. import com.obs.services.model.PostSignatureRequest;
  20. import com.obs.services.model.PostSignatureResponse;
  21. import com.ruoyi.common.constant.BaseSourceConstant;
  22. import com.ruoyi.common.core.domain.BaseIdPo;
  23. import com.ruoyi.common.exception.ServiceException;
  24. import com.ruoyi.common.utils.wrapper.IWrapper;
  25. import org.springframework.beans.factory.annotation.Value;
  26. import org.springframework.stereotype.Service;
  27. import org.springframework.transaction.annotation.Transactional;
  28. import java.io.File;
  29. import java.util.*;
  30. import java.util.stream.Collectors;
  31. /**
  32. * <p>
  33. * 文件表 服务实现类
  34. * </p>
  35. *
  36. * @author zlj
  37. * @since 2023-03-14
  38. */
  39. @Service
  40. public class FileInfoServiceImpl extends ServiceImpl<FileInfoMapper, FileInfo> implements FileInfoService {
  41. @Value("${obs.ak}")
  42. private String ak;
  43. @Value("${obs.sk}")
  44. private String sk;
  45. @Value("${obs.endPoint}")
  46. private String endPoint;
  47. @Value("${obs.url}")
  48. private String url;
  49. @Value("${obs.bucketName}")
  50. private String bucketName;
  51. @Value("${spring.profiles.active}")
  52. private String active;
  53. @Value("${ruoyi.name}")
  54. private String name;
  55. @Override
  56. public SingVo getSing(SingDto dto) {
  57. String fileName = dto.getFileName();
  58. if (fileName.length() > 100) {
  59. throw new ServiceException("文件名过长,请缩短后重试!!!");
  60. }
  61. SingVo singVo = new SingVo();
  62. // 文件后缀名
  63. String suffix = FileUtil.getSuffix(dto.getFileName());
  64. // 文件路径
  65. String objectKey = new StringJoiner("/")
  66. .add(name)
  67. .add(active)
  68. .add(DateUtil.format(new Date(), "yyyy/MM/dd"))
  69. .add(IdUtil.fastSimpleUUID() + (ObjectUtil.isEmpty(suffix) ? "" : "." + suffix))
  70. .toString();
  71. ObsClient obsClient = null;
  72. try {
  73. // 获取oss链接客户端
  74. obsClient = getObsClient();
  75. // 指定签名有效期为10秒
  76. long currentTimeMillis = System.currentTimeMillis() + 1000 * 10;
  77. // 获取签名
  78. PostSignatureRequest request = new PostSignatureRequest(currentTimeMillis, bucketName, objectKey);
  79. PostSignatureResponse temporarySignature = obsClient.createPostSignature(request);
  80. // 封装签名
  81. Map<String, String> body = new LinkedHashMap<>();
  82. body.put("policy", temporarySignature.getPolicy());
  83. body.put("AccessKeyId", ak);
  84. body.put("signature", temporarySignature.getSignature());
  85. body.put("key", objectKey);
  86. singVo.setUploadBody(body);
  87. } catch (Exception e) {
  88. throw new ServiceException("获取签名失败");
  89. } finally {
  90. IoUtil.close(obsClient);
  91. }
  92. // 保存文件
  93. FileInfo fileInfo = new FileInfo();
  94. fileInfo.setFileUrl(objectKey);
  95. fileInfo.setFileName(dto.getFileName());
  96. save(fileInfo);
  97. // 封装文件信息
  98. singVo.setUploadUrl("https://" + bucketName + "." + endPoint);
  99. singVo.setId(fileInfo.getId());
  100. singVo.setFileName(dto.getFileName());
  101. singVo.setFileUrl(url + objectKey);
  102. return singVo;
  103. }
  104. @DS(BaseSourceConstant.BASE)
  105. @Override
  106. public Map<Long, List<FileInfoVo>> getList(FileInfoSelectDto dto) {
  107. if (ObjectUtil.isEmpty(dto.getBusinessIdList())) {
  108. return new HashMap<>();
  109. }
  110. IWrapper<Object> wrapper = IWrapper.getWrapper();
  111. wrapper.in("fi", FileInfo::getBusinessId, dto.getBusinessIdList());
  112. wrapper.eq("fi", FileInfo::getBusinessType, dto.getFileType());
  113. List<FileInfoVo> list = this.baseMapper.getList(wrapper);
  114. if (list.size() == 0) {
  115. return new HashMap<>();
  116. }
  117. return list.stream()
  118. .peek(fileInfoVo -> fileInfoVo.setFileUrl(url + fileInfoVo.getFileUrl()))
  119. .collect(Collectors.groupingBy(FileInfoVo::getBusinessId));
  120. }
  121. /**
  122. * @param obsFileList 文件列表
  123. * @param businessId 业务id
  124. * @param businessType 业务文件类型
  125. */
  126. @DS(BaseSourceConstant.BASE)
  127. @Override
  128. public void saveFile(List<ObsFile> obsFileList, Long businessId, Integer businessType) {
  129. // 切换到从库
  130. if (obsFileList == null || obsFileList.size() == 0) {
  131. return;
  132. }
  133. List<FileInfo> fileInfoList = BeanUtil.copyToList(obsFileList, FileInfo.class);
  134. for (FileInfo fileInfo : fileInfoList) {
  135. fileInfo.setFileUrl(null);
  136. fileInfo.setBusinessId(businessId);
  137. fileInfo.setBusinessType(businessType);
  138. }
  139. this.updateBatchById(fileInfoList);
  140. }
  141. /**
  142. * 保存文件--直接插入
  143. * @param obsFileList 文件列表
  144. * @param businessId 业务id
  145. * @param businessType 业务文件类型
  146. */
  147. @DS(BaseSourceConstant.BASE)
  148. @Override
  149. public void saveAllFile(List<ObsFile> obsFileList, Long businessId, Integer businessType) {
  150. if (obsFileList == null || obsFileList.size() == 0) {
  151. return;
  152. }
  153. List<FileInfo> fileInfoList = BeanUtil.copyToList(obsFileList, FileInfo.class);
  154. for (FileInfo fileInfo : fileInfoList) {
  155. fileInfo.setId(IdWorker.getId());
  156. fileInfo.setBusinessId(businessId);
  157. fileInfo.setBusinessType(businessType);
  158. }
  159. this.saveBatch(fileInfoList);
  160. }
  161. /**
  162. *
  163. * @param obsFileList 文件列表
  164. * @param businessId 业务id
  165. * @param businessType 业务文件类型
  166. */
  167. @DS(BaseSourceConstant.BASE)
  168. @Override
  169. public void editFile(List<ObsFile> obsFileList, Long businessId, Integer businessType) {
  170. if (obsFileList == null || obsFileList.size() == 0) {
  171. this.remove(q -> q.eq(FileInfo::getBusinessId, businessId).eq(FileInfo::getBusinessType, businessType));
  172. return;
  173. }
  174. // 删除不包含在此列表的业务id文件
  175. List<Long> obsFileId = obsFileList.stream().map(ObsFile::getId).collect(Collectors.toList());
  176. this.remove(q -> q.notIn(ObjectUtil.isNotEmpty(obsFileId), BaseIdPo::getId, obsFileId)
  177. .eq(FileInfo::getBusinessId, businessId).eq(FileInfo::getBusinessType, businessType));
  178. // 更新在此列表的文件
  179. saveFile(obsFileList, businessId, businessType);
  180. }
  181. /**
  182. * !!!必须加上Transactional 更改事务传播行为,否则数据源将被缓存,造成数据源切换失败
  183. *
  184. * @param businessId 业务id
  185. * @param businessType 业务文件类型
  186. */
  187. @DS(BaseSourceConstant.BASE)
  188. @Override
  189. public void removeFile(Long businessId, Integer businessType) {
  190. this.remove(q -> q
  191. .eq(FileInfo::getBusinessId, businessId)
  192. .eq(FileInfo::getBusinessType, businessType));
  193. }
  194. /**
  195. * !!!必须加上Transactional 更改事务传播行为,否则数据源将被缓存,造成数据源切换失败
  196. *
  197. * @param businessId 业务id
  198. */
  199. @DS(BaseSourceConstant.BASE)
  200. @Override
  201. public void removeFile(Long businessId) {
  202. this.remove(q -> q.eq(FileInfo::getBusinessId, businessId));
  203. }
  204. /**
  205. * 交换业务ID
  206. * @param oldBusinessId 旧业务id
  207. * @param newBusinessId 新业务id
  208. */
  209. @DS(BaseSourceConstant.BASE)
  210. @Override
  211. @Transactional(rollbackFor = Exception.class)
  212. public void exchangeBusinessId(Long oldBusinessId, Long newBusinessId) {
  213. List<FileInfo> oldFile = this.list(Wrappers.<FileInfo>query().lambda().select(FileInfo::getId).eq(FileInfo::getBusinessId,oldBusinessId));
  214. List<FileInfo> newFile = this.list(Wrappers.<FileInfo>query().lambda().select(FileInfo::getId).eq(FileInfo::getBusinessId,newBusinessId));
  215. if(CollectionUtils.isNotEmpty(oldFile)){
  216. List<Long> ids = oldFile.stream().map(FileInfo::getId).collect(Collectors.toList());
  217. this.update(Wrappers.<FileInfo>update().lambda().set(FileInfo::getBusinessId,newBusinessId).in(FileInfo::getId,ids));
  218. }
  219. if(CollectionUtils.isNotEmpty(newFile)){
  220. List<Long> ids = newFile.stream().map(FileInfo::getId).collect(Collectors.toList());
  221. this.update(Wrappers.<FileInfo>update().lambda().set(FileInfo::getBusinessId,oldBusinessId).in(FileInfo::getId,ids));
  222. }
  223. }
  224. /**
  225. * 获取oss链接客户端
  226. */
  227. private ObsClient getObsClient() {
  228. return new ObsClient(ak, sk, endPoint);
  229. }
  230. /**
  231. * 判断文件是否已经绑定业务 是将文件复制一份并保存
  232. *
  233. * @param fileList 文件列表
  234. * @param businessId 业务id
  235. * @param businessType 业务文件类型
  236. */
  237. @DS(BaseSourceConstant.BASE)
  238. @Override
  239. public void copyFileAndSave(List<ObsFile> fileList, Long businessId, Integer businessType) {
  240. if (ObjectUtils.isEmpty(fileList)) {
  241. return;
  242. }
  243. List<Long> fids = fileList.stream().map(ObsFile::getId).collect(Collectors.toList());
  244. Map<Long, FileInfo> fileInfoMap = this.mapKEntity(FileInfo::getId, q -> q.in(FileInfo::getId, fids));
  245. List<FileInfo> newFileInfo = new ArrayList<>();
  246. for (ObsFile obsFile : fileList) {
  247. FileInfo fileInfo = fileInfoMap.get(obsFile.getId());
  248. if (ObjectUtils.isEmpty(fileInfo)) {
  249. continue;
  250. }
  251. //如果文件已经有业务id了 且业务id不是当前业务id 就将文件复制一份
  252. if (ObjectUtils.isNotEmpty(fileInfo.getBusinessId()) && !businessId.equals(fileInfo.getBusinessId())) {
  253. long id = IdWorker.getId();
  254. fileInfo.setId(id);
  255. obsFile.setId(id);
  256. newFileInfo.add(fileInfo);
  257. }
  258. }
  259. this.saveBatch(newFileInfo);
  260. saveFile(fileList, businessId, businessType);
  261. }
  262. }