package cn.iocoder.yudao.module.mes.service.safety; import cn.hutool.core.io.IoUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.module.infra.api.file.FileApi; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** * 安全生产 - 移动端附件上传 Service * *

巡检、隐患、作业票、演练等环节的现场拍照统一走这里: * 落到 infra 文件存储,返回可访问 URL,多个附件逗号拼接后存入业务表。

* * @author 超级管理员 */ @Service @Slf4j public class SafetyFileService { /** 单个文件最大 20MB,手机原图裁切后足够 */ private static final long MAX_SIZE = 20L * 1024 * 1024; /** 允许的图片类型 */ private static final List ALLOWED_EXT = List.of( "jpg", "jpeg", "png", "webp", "heic", "gif", "bmp", "pdf", "doc", "docx", "xls", "xlsx"); @Resource private FileApi fileApi; /** * 上传单个文件 * * @param file 文件 * @param bizType 业务类型(safety/inspection、safety/hazard 等),用作存储目录 * @return 文件访问 URL */ public String upload(MultipartFile file, String bizType) { if (file == null || file.isEmpty()) { throw new IllegalArgumentException("上传文件不能为空"); } if (file.getSize() > MAX_SIZE) { throw new IllegalArgumentException("单个文件不能超过 20MB"); } String originalName = StrUtil.blankToDefault(file.getOriginalFilename(), "photo.jpg"); String ext = StrUtil.subAfter(originalName, ".", true).toLowerCase(); if (StrUtil.isNotBlank(ext) && !ALLOWED_EXT.contains(ext)) { throw new IllegalArgumentException("不支持的文件类型:" + ext); } byte[] content; try { content = IoUtil.readBytes(file.getInputStream()); } catch (IOException e) { throw new IllegalStateException("读取上传文件失败", e); } String directory = StrUtil.blankToDefault(bizType, "safety") + "/" + java.time.LocalDate.now(); return fileApi.createFile(content, originalName, directory, file.getContentType()); } /** * 批量上传(移动端一次拍多张) * * @return 文件 URL 列表 */ public List uploadBatch(List files, String bizType) { if (files == null || files.isEmpty()) { return List.of(); } if (files.size() > 9) { throw new IllegalArgumentException("单次最多上传 9 张"); } List urls = new ArrayList<>(); for (MultipartFile file : files) { urls.add(upload(file, bizType)); } return urls; } /** * 删除附件(从逗号串里剔除某个 URL) */ public String removeUrl(String urls, String target) { if (StrUtil.isBlank(urls) || StrUtil.isBlank(target)) { return urls; } return Arrays.stream(urls.split(",")) .map(String::trim) .filter(url -> !url.equals(target.trim())) .reduce((a, b) -> a + "," + b) .orElse(""); } }