新增附件管理模块

This commit is contained in:
刘倡
2025-07-23 16:54:21 +08:00
parent a649a6f515
commit c322af6e9e
12 changed files with 389 additions and 0 deletions

View File

@ -0,0 +1,23 @@
package com.coscoshipping.ebtp.system.attachment.client;
import com.chinaunicom.mall.ebtp.common.base.entity.BaseResponse;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
@FeignClient(value = "data-service-document-center",url = "http://10.242.31.158:8100/doc", fallbackFactory = DocumentServerFeignFallbackFactory.class)
//@FeignClient(value = "${mconfig.feign.name.document}", fallbackFactory = DocumentServerFeignFallbackFactory.class)
public interface DocumentServerFeignClient {
@GetMapping("api/data-service-document-center/outer/v1.0/files/getSecretKey")
BaseResponse<String> getSecretKey();
// @GetMapping(value ="api/data-service-document-center/outer/v1.0/files/getDownload")
@GetMapping(value = "api/data-service-document-center/outer/v1.0/files/getDownload")
feign.Response getDownload(@RequestParam String fileId, @RequestParam String documentSecretKey);
}

View File

@ -0,0 +1,32 @@
package com.coscoshipping.ebtp.system.attachment.client;
import cn.hutool.core.exceptions.ExceptionUtil;
import com.chinaunicom.mall.ebtp.common.base.entity.BaseResponse;
import feign.Response;
import feign.hystrix.FallbackFactory;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
@Component
@Slf4j
public class DocumentServerFeignFallbackFactory implements FallbackFactory<DocumentServerFeignClient> {
@Override
public DocumentServerFeignClient create(Throwable throwable) {
DocumentServerFeignClient back = new DocumentServerFeignClient() {
@Override
public BaseResponse<String> getSecretKey() {
return new BaseResponse<>();
}
@Override
public Response getDownload(String fileId, String documentSecretKey) {
log.info("文档中心异常,下载失败");
return null;
}
};
log.error(ExceptionUtil.stacktraceToString(throwable));
return back;
}
}

View File

@ -0,0 +1,58 @@
package com.coscoshipping.ebtp.system.attachment.controller;
import com.chinaunicom.ebtp.mall.cloud.attachment.sdk.api.AttachmentClient;
import com.chinaunicom.ebtp.mall.cloud.attachment.sdk.model.AttachmentEntity;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
@Slf4j
@RestController
@RequestMapping("/v1/attachment")
public class AttachmentOssController {
/* 附件工具 */
@Autowired
private AttachmentClient attachmentClient;
/**
* 使用对象Id查询附件信息
* pbr
*
* @param objectId
* @return org.springframework.http.ResponseEntity<java.util.Map < java.lang.String, java.lang.Object>>
* @author liuh
*/
@Operation(summary = "使用对象Id查询附件信息")
@GetMapping(value = "/find/oid/{oid}")
public ResponseEntity<Map<String, Object>> findByObjectId(
@Parameter(description = "对象Id") @PathVariable("oid") String objectId) {
// 查询cos中存储的指定对象明细
Optional<AttachmentEntity> op = attachmentClient.findByObjectId(objectId);
// 创建vo模型
Map<String, Object> result = new HashMap<String, Object>();
boolean esists = op.isPresent();
result.put("exists", esists);
if (esists) {
result.put("item", op.get());
}
return ResponseEntity.ok(result);
}
}

View File

@ -0,0 +1,74 @@
package com.coscoshipping.ebtp.system.attachment.controller;
import cn.hutool.core.util.IdUtil;
import com.coscoshipping.ebtp.system.attachment.entity.vo.SnowFlakerVO;
import io.swagger.v3.oas.annotations.Operation;
import org.apache.commons.lang3.RandomUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.SystemUtils;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
import java.net.Inet4Address;
import java.net.UnknownHostException;
/**
* 业务id接口
*
* @author Ajaxfan
*/
@RestController
@RequestMapping("/v1/business")
public class AttachmentSnowflakerController {
private final static long WORKER_ID;
private final static long DATACENTER_ID;
static {
WORKER_ID = getWorkId();
DATACENTER_ID = getDataCenterId();
}
/**
* 派发新的业务Id
* pbr
*
* @param
* @return com.chinaunicom.mall.ebtp.attachment.entity.vo.SnowFlakerVO
* @author liuh
*/
@Operation(summary = "派发新的业务Id")
@GetMapping("/id")
@ResponseStatus(code = HttpStatus.OK)
public SnowFlakerVO snowFlakerId() {
return new SnowFlakerVO().setId(IdUtil.getSnowflake(WORKER_ID, DATACENTER_ID).nextIdStr());
}
private static Long getWorkId() {
try {
String hostAddress = Inet4Address.getLocalHost().getHostAddress();
int[] ints = StringUtils.toCodePoints(hostAddress);
int sums = 0;
for (int b : ints) {
sums += b;
}
return (long) (sums % 32);
} catch (UnknownHostException e) {
// 如果获取失败,则使用随机数备用
return RandomUtils.nextLong(0, 31);
}
}
private static Long getDataCenterId() {
int[] ints = StringUtils.toCodePoints(SystemUtils.getHostName());
int sums = 0;
for (int i : ints) {
sums += i;
}
return (long) (sums % 32);
}
}

View File

@ -0,0 +1,24 @@
package com.coscoshipping.ebtp.system.attachment.entity.dao;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.experimental.Accessors;
@Data
@TableName(value = "biz_oss_object_tbl")
@Accessors(chain = true)
public class OssObjectDao {
/* 对象ID */
@TableId
private String id;
/* 业务Id */
private String bid;
/* 文件名称 */
private String filename;
}

View File

@ -0,0 +1,12 @@
package com.coscoshipping.ebtp.system.attachment.entity.dto;
import lombok.Data;
import java.util.List;
@Data
public class OssFinderDTO {
private List<String> bidList;
}

View File

@ -0,0 +1,19 @@
package com.coscoshipping.ebtp.system.attachment.entity.po;
import lombok.Data;
import lombok.experimental.Accessors;
@Data
@Accessors(chain = true)
public class AttachmentPO {
/* 附件ID */
private String id;
/* 业务ID */
private String bid;
/* 附件名称 */
private String filename;
}

View File

@ -0,0 +1,32 @@
package com.coscoshipping.ebtp.system.attachment.entity.vo;
import lombok.Data;
import lombok.experimental.Accessors;
import java.util.Optional;
@Data
@Accessors(chain = true)
public class FeedbackMessageVO {
private Boolean success;
private String oid;
private String message;
public FeedbackMessageVO(String oid) {
this.success = Optional.ofNullable(oid).isPresent();
if (!this.success) {
this.message = "文档中心异常或无效的文件类型";
}
this.oid = oid;
}
public FeedbackMessageVO(Boolean success) {
if (!this.success) {
this.message = "文档中心异常或无效的文件类型";
}
this.success = success;
}
}

View File

@ -0,0 +1,12 @@
package com.coscoshipping.ebtp.system.attachment.entity.vo;
import lombok.Data;
import lombok.experimental.Accessors;
@Data
@Accessors(chain = true)
public class SnowFlakerVO {
private String id;
}

View File

@ -0,0 +1,27 @@
package com.coscoshipping.ebtp.system.attachment.entity.vo;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Data;
import org.springframework.web.multipart.MultipartFile;
import javax.validation.constraints.NotNull;
@Data
public class UploadVO {
@NotNull(message = "业务id不嫩为空")
private String businessId;
/**
* 文件流
*/
@JsonIgnore
@NotNull(message = "附件不能为空")
private MultipartFile file;
/**
* bid下是否唯一
*/
private boolean only;
}

View File

@ -0,0 +1,13 @@
package com.coscoshipping.ebtp.system.attachment.handler;
import com.coscoshipping.ebtp.system.attachment.entity.dao.OssObjectDao;
import java.util.Optional;
@FunctionalInterface
public interface OssStorageHandler<T> {
Optional<OssObjectDao> save(T t);
}

View File

@ -0,0 +1,63 @@
package com.coscoshipping.ebtp.system.attachment.handler.impl;
import com.chinaunicom.ebtp.mall.cloud.attachment.sdk.api.AttachmentClient;
import com.chinaunicom.ebtp.mall.cloud.attachment.sdk.model.UploadObject;
import com.coscoshipping.ebtp.system.attachment.entity.dao.OssObjectDao;
import com.coscoshipping.ebtp.system.attachment.entity.vo.UploadVO;
import com.coscoshipping.ebtp.system.attachment.handler.OssStorageHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import org.springframework.web.multipart.MultipartFile;
import java.util.Optional;
/**
* 文件对象存储到OSS
*
* @author Ajaxfan
*/
@Slf4j
@Component
public class OssStorageHandlerImpl implements OssStorageHandler<UploadVO> {
/* 附件工具 */
private @Autowired
AttachmentClient attachmentClient;
@Override
public Optional<OssObjectDao> save(UploadVO vo) {
return Optional.of(vo).map(this::pushObjectToOss);
}
/**
* 对象推入到 OSS
*
* @param vo
* @return
*/
private OssObjectDao pushObjectToOss(UploadVO vo) {
try {
MultipartFile multipartFile = vo.getFile();
Assert.notNull(multipartFile, "无效的附件");
String businessId = vo.getBusinessId();
Assert.notNull(businessId, "业务id不能为空");
String filename = multipartFile.getOriginalFilename();
// 资源上传, 需要提供业务ID和待上传文件对象
Optional<UploadObject> op = attachmentClient.upload(businessId, filename, multipartFile.getBytes(), vo.isOnly());
// 检验结果的有效性
if (op.isPresent()) {
return new OssObjectDao().setId(op.get().getId()).setFilename(filename).setBid(businessId);
}
} catch (Exception e) {
log.error(e.getMessage());
}
return null;
}
}