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
|
*
|
* <p>巡检、隐患、作业票、演练等环节的现场拍照统一走这里:
|
* 落到 infra 文件存储,返回可访问 URL,多个附件逗号拼接后存入业务表。</p>
|
*
|
* @author 超级管理员
|
*/
|
@Service
|
@Slf4j
|
public class SafetyFileService {
|
|
/** 单个文件最大 20MB,手机原图裁切后足够 */
|
private static final long MAX_SIZE = 20L * 1024 * 1024;
|
/** 允许的图片类型 */
|
private static final List<String> 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<String> uploadBatch(List<MultipartFile> files, String bizType) {
|
if (files == null || files.isEmpty()) {
|
return List.of();
|
}
|
if (files.size() > 9) {
|
throw new IllegalArgumentException("单次最多上传 9 张");
|
}
|
List<String> 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("");
|
}
|
|
}
|