fix(file): support truck appointment attachments
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
package com.baiyue.file.service;
|
||||
import com.baiyue.common.core.api.ResultCode;import com.baiyue.common.core.exception.BizException;import jakarta.annotation.PostConstruct;import org.springframework.beans.factory.annotation.Value;import org.springframework.stereotype.Component;import org.springframework.web.multipart.MultipartFile;import java.nio.file.*;import java.security.*;import java.util.*;
|
||||
@Component public class BusinessFileStorage{
|
||||
private static final long MAX=10L*1024*1024;private static final Set<String>TYPES=Set.of("text/plain","application/pdf","image/jpeg","image/png");@Value("${baiyue.file.storage-root}")Path configured;Path root;@PostConstruct void init(){root=configured.toAbsolutePath().normalize();}
|
||||
Stored storeLoading(long tenantId,long businessId,MultipartFile file){return store(tenantId,Long.toString(businessId),file);}
|
||||
Stored store(long tenantId,String businessId,MultipartFile file){if(file==null||file.isEmpty())throw bad("附件不能为空");if(file.getSize()>MAX)throw bad("附件不能超过10MB");String type=file.getContentType()==null?"":file.getContentType().toLowerCase(Locale.ROOT);if(!TYPES.contains(type))throw bad("附件仅支持TXT、PDF、JPG、PNG");String name=file.getOriginalFilename()==null?"attachment":Path.of(file.getOriginalFilename()).getFileName().toString();String suffix=name.contains(".")?name.substring(name.lastIndexOf('.')):"";String key="business-files/"+tenantId+"/"+businessId+"/"+UUID.randomUUID()+suffix;Path target=root.resolve(key).normalize();if(!target.startsWith(root))throw new BizException(ResultCode.FORBIDDEN,"文件路径越界");try{Files.createDirectories(target.getParent());file.transferTo(target);byte[]hash=MessageDigest.getInstance("SHA-256").digest(Files.readAllBytes(target));return new Stored(key,type,file.getSize(),HexFormat.of().formatHex(hash),name);}catch(Exception e){throw new BizException(ResultCode.SERVICE_UNAVAILABLE,"附件保存失败");}}
|
||||
record Stored(String objectKey,String contentType,long size,String sha256,String originalName){}private static BizException bad(String m){return new BizException(ResultCode.BAD_REQUEST,m);}
|
||||
}
|
||||
@@ -13,7 +13,7 @@ import java.time.LocalDateTime;
|
||||
@Service
|
||||
public class InternalBusinessFileService {
|
||||
private static final String TRUCK_ATTACHMENT = "TRUCK_APPOINTMENT_ATTACHMENT";
|
||||
@Resource FileObjectMapper files; @Resource MeasurementImageStorage storage;
|
||||
@Resource FileObjectMapper files; @Resource BusinessFileStorage storage;
|
||||
public Metadata upload(long tenantId,String businessType,String businessId,long operatorId,MultipartFile file){if(tenantId<=0||operatorId<=0)throw new BizException(ResultCode.BAD_REQUEST,"归属和操作人必须有效");if(!TRUCK_ATTACHMENT.equals(businessType))throw new BizException(ResultCode.BAD_REQUEST,"不支持的附件业务类型");long appointmentId;try{appointmentId=Long.parseLong(businessId);}catch(NumberFormatException ex){throw new BizException(ResultCode.BAD_REQUEST,"预约ID格式无效");}if(appointmentId<=0)throw new BizException(ResultCode.BAD_REQUEST,"预约ID必须有效");var stored=storage.storeLoading(tenantId,appointmentId,file);FileObjectEntity value=new FileObjectEntity();value.setTenantId(tenantId);value.setBusinessType(TRUCK_ATTACHMENT);value.setBusinessId(businessId);value.setOriginalName(stored.originalName());value.setObjectKey(stored.objectKey());value.setStorageProvider("LOCAL");value.setBucketName("loading-evidence");value.setContentType(stored.contentType());value.setSizeBytes(stored.size());value.setSha256(stored.sha256());value.setStatus("ACTIVE");value.setCreatedBy(operatorId);value.setUpdatedBy(operatorId);value.setCreatedAt(LocalDateTime.now());value.setUpdatedAt(value.getCreatedAt());value.setDeleted(false);value.setVersion(0);if(files.insert(value)!=1)throw new BizException(ResultCode.INTERNAL_ERROR,"附件元数据保存失败");return new Metadata(value.getId(),tenantId,TRUCK_ATTACHMENT,businessId,value.getOriginalName(),value.getSha256());}
|
||||
public Metadata metadata(long tenantId,String businessType,String businessId,long fileId){FileObjectEntity value=files.selectOne(new LambdaQueryWrapper<FileObjectEntity>().eq(FileObjectEntity::getTenantId,tenantId).eq(FileObjectEntity::getBusinessType,businessType).eq(FileObjectEntity::getBusinessId,businessId).eq(FileObjectEntity::getId,fileId).eq(FileObjectEntity::getStatus,"ACTIVE").eq(FileObjectEntity::getDeleted,false));if(value==null)throw new BizException(ResultCode.NOT_FOUND,"业务附件不存在或归属不匹配");return new Metadata(value.getId(),value.getTenantId(),value.getBusinessType(),value.getBusinessId(),value.getOriginalName(),value.getSha256());}
|
||||
public record Metadata(Long fileId,Long tenantId,String businessType,String businessId,String fileName,String sha256){}
|
||||
|
||||
Reference in New Issue
Block a user