package com.fjhx.file.service.impl; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.date.DateUtil; import cn.hutool.core.io.FileUtil; import cn.hutool.core.io.IoUtil; import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.ObjectUtil; import com.baomidou.dynamic.datasource.annotation.DS; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.fjhx.file.entity.*; import com.fjhx.file.mapper.FileInfoMapper; import com.fjhx.file.service.FileInfoService; import com.obs.services.ObsClient; import com.obs.services.model.PostSignatureRequest; import com.obs.services.model.PostSignatureResponse; import com.ruoyi.common.constant.BaseSourceConstant; import com.ruoyi.common.core.domain.BaseIdPo; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.utils.wrapper.IWrapper; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import java.util.*; import java.util.stream.Collectors; /** * <p> * 文件表 服务实现类 * </p> * * @author zlj * @since 2023-03-14 */ @Service public class FileInfoServiceImpl extends ServiceImpl<FileInfoMapper, FileInfo> implements FileInfoService { @Value("${obs.ak}") private String ak; @Value("${obs.sk}") private String sk; @Value("${obs.endPoint}") private String endPoint; @Value("${obs.url}") private String url; @Value("${obs.bucketName}") private String bucketName; @Value("${spring.profiles.active}") private String active; @Override public SingVo getSing(SingDto dto) { String fileName = dto.getFileName(); if (fileName.length()>100){ throw new ServiceException("文件名过长,请缩短后重试!!!"); } SingVo singVo = new SingVo(); // 文件后缀名 String suffix = FileUtil.getSuffix(dto.getFileName()); // 文件路径 String objectKey = new StringJoiner("/") .add("byteSailing") .add(active) .add(DateUtil.format(new Date(), "yyyy/MM/dd")) .add(IdUtil.fastSimpleUUID() + (ObjectUtil.isEmpty(suffix) ? "" : "." + suffix)) .toString(); ObsClient obsClient = null; try { // 获取oss链接客户端 obsClient = getObsClient(); // 指定签名有效期为10秒 long currentTimeMillis = System.currentTimeMillis() + 1000 * 10; // 获取签名 PostSignatureRequest request = new PostSignatureRequest(currentTimeMillis, bucketName, objectKey); PostSignatureResponse temporarySignature = obsClient.createPostSignature(request); // 封装签名 Map<String, String> body = new LinkedHashMap<>(); body.put("policy", temporarySignature.getPolicy()); body.put("AccessKeyId", ak); body.put("signature", temporarySignature.getSignature()); body.put("key", objectKey); singVo.setUploadBody(body); } catch (Exception e) { throw new ServiceException("获取签名失败"); } finally { IoUtil.close(obsClient); } // 保存文件 FileInfo fileInfo = new FileInfo(); fileInfo.setFileUrl(objectKey); fileInfo.setFileName(dto.getFileName()); save(fileInfo); // 封装文件信息 singVo.setUploadUrl("https://" + bucketName + "." + endPoint); singVo.setId(fileInfo.getId()); singVo.setFileName(dto.getFileName()); singVo.setFileUrl(url + objectKey); return singVo; } @DS(BaseSourceConstant.BASE) @Override public Map<Long, List<FileInfoVo>> getList(FileInfoSelectDto dto) { if (ObjectUtil.isEmpty(dto.getBusinessIdList())) { return new HashMap<>(); } IWrapper<Object> wrapper = IWrapper.getWrapper(); wrapper.in("fi", FileInfo::getBusinessId, dto.getBusinessIdList()); wrapper.eq("fi", FileInfo::getBusinessType, dto.getFileType()); List<FileInfoVo> list = this.baseMapper.getList(wrapper); if (list.size() == 0) { return new HashMap<>(); } return list.stream() .peek(fileInfoVo -> fileInfoVo.setFileUrl(url + fileInfoVo.getFileUrl())) .collect(Collectors.groupingBy(FileInfoVo::getBusinessId)); } /** * !!!必须加上Transactional 更改事务传播行为,否则数据源将被缓存,造成数据源切换失败 * * @param obsFileList 文件列表 * @param businessId 业务id * @param businessType 业务文件类型 */ @DS(BaseSourceConstant.BASE) @Override public void saveFile(List<ObsFile> obsFileList, Long businessId, Integer businessType) { // 切换到从库 if (obsFileList == null || obsFileList.size() == 0) { return; } List<FileInfo> fileInfoList = BeanUtil.copyToList(obsFileList, FileInfo.class); for (FileInfo fileInfo : fileInfoList) { fileInfo.setBusinessId(businessId); fileInfo.setBusinessType(businessType); } this.updateBatchById(fileInfoList); } /** * !!!必须加上Transactional 更改事务传播行为,否则数据源将被缓存,造成数据源切换失败 * * @param obsFileList 文件列表 * @param businessId 业务id * @param businessType 业务文件类型 */ @DS(BaseSourceConstant.BASE) @Override public void editFile(List<ObsFile> obsFileList, Long businessId, Integer businessType) { if (obsFileList == null || obsFileList.size() == 0) { this.remove(q -> q.eq(FileInfo::getBusinessId, businessId).eq(FileInfo::getBusinessType, businessType)); return; } // 删除不包含在此列表的业务id文件 List<Long> obsFileId = obsFileList.stream().map(ObsFile::getId).collect(Collectors.toList()); this.remove(q -> q.notIn(ObjectUtil.isNotEmpty(obsFileId), BaseIdPo::getId, obsFileId) .eq(FileInfo::getBusinessId, businessId).eq(FileInfo::getBusinessType, businessType)); // 更新在此列表的文件 saveFile(obsFileList, businessId, businessType); } /** * !!!必须加上Transactional 更改事务传播行为,否则数据源将被缓存,造成数据源切换失败 * * @param businessId 业务id * @param businessType 业务文件类型 */ @DS(BaseSourceConstant.BASE) @Override public void removeFile(Long businessId, Integer businessType) { this.remove(q -> q .eq(FileInfo::getBusinessId, businessId) .eq(FileInfo::getBusinessType, businessType)); } /** * !!!必须加上Transactional 更改事务传播行为,否则数据源将被缓存,造成数据源切换失败 * * @param businessId 业务id */ @DS(BaseSourceConstant.BASE) @Override public void removeFile(Long businessId) { this.remove(q -> q.eq(FileInfo::getBusinessId, businessId)); } /** * 获取oss链接客户端 */ private ObsClient getObsClient() { return new ObsClient(ak, sk, endPoint); } }