完成新需求

This commit is contained in:
super
2026-03-20 14:26:34 +08:00
parent 43d508f527
commit 92d3fc965b
71 changed files with 3265 additions and 540 deletions
@@ -0,0 +1,37 @@
package com.nanri.aiimage.modules.file.controller;
import com.nanri.aiimage.common.api.ApiResponse;
import com.nanri.aiimage.modules.file.model.vo.UploadFileVo;
import com.nanri.aiimage.modules.file.service.LocalFileStorageService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/files")
@Tag(name = "文件上传", description = "用于前端将本地文件上传到后端临时目录,后续任务接口基于 fileKey 进行处理")
public class FileUploadController {
private final LocalFileStorageService localFileStorageService;
@PostMapping("/upload")
@Operation(
summary = "上传临时文件",
description = """
上传本地 Excel 文件到后端临时目录,返回 fileKey。
该接口不是给浏览器页面直接使用的最终业务接口,而是给 Python 桌面端壳做文件中转:
- 桌面端先选本地文件;
- 再调用本接口上传到 Java 临时目录;
- 然后把 fileKey 传给 dedupe/convert/split 执行接口;
- 处理完成后,桌面端再调用下载接口把结果文件保存回用户本地目录。
""")
public ApiResponse<UploadFileVo> upload(MultipartFile file) throws Exception {
return ApiResponse.success(localFileStorageService.saveTempFile(file));
}
}
@@ -0,0 +1,21 @@
package com.nanri.aiimage.modules.file.model.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
@Schema(description = "上传文件返回信息")
public class UploadFileVo {
@Schema(description = "临时文件键")
private String fileKey;
@Schema(description = "原始文件名")
private String originalFilename;
@Schema(description = "本地暂存路径")
private String localPath;
@Schema(description = "文件大小")
private Long size;
}
@@ -0,0 +1,39 @@
package com.nanri.aiimage.modules.file.service;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.IdUtil;
import com.nanri.aiimage.config.StorageProperties;
import com.nanri.aiimage.modules.file.model.vo.UploadFileVo;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
@Service
@RequiredArgsConstructor
public class LocalFileStorageService {
private final StorageProperties storageProperties;
public UploadFileVo saveTempFile(MultipartFile file) throws IOException {
File tempDir = FileUtil.file(storageProperties.getLocalTempDir());
File parentDir = tempDir.getParentFile();
if (parentDir != null) {
FileUtil.mkdir(parentDir);
}
FileUtil.mkdir(tempDir);
String fileKey = IdUtil.fastSimpleUUID();
String extName = FileUtil.extName(file.getOriginalFilename());
File target = FileUtil.file(tempDir, fileKey + (extName.isEmpty() ? "" : "." + extName));
file.transferTo(target);
UploadFileVo vo = new UploadFileVo();
vo.setFileKey(fileKey);
vo.setOriginalFilename(file.getOriginalFilename());
vo.setLocalPath(target.getAbsolutePath());
vo.setSize(file.getSize());
return vo;
}
}
@@ -0,0 +1,49 @@
package com.nanri.aiimage.modules.file.service.oss;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.nanri.aiimage.config.OssProperties;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.io.File;
import java.net.URL;
import java.util.Date;
import java.util.UUID;
@Service
@RequiredArgsConstructor
public class OssStorageService {
private final OssProperties ossProperties;
public String uploadResultFile(File file, String moduleType) {
String objectKey = String.format("result/%s/%s/%s", moduleType.toLowerCase(), UUID.randomUUID(), file.getName());
OSS ossClient = new OSSClientBuilder().build(
"https://" + ossProperties.getEndpoint(),
ossProperties.getAccessKeyId(),
ossProperties.getAccessKeySecret()
);
try {
ossClient.putObject(ossProperties.getBucket(), objectKey, file);
return objectKey;
} finally {
ossClient.shutdown();
}
}
public String generateDownloadUrl(String objectKey) {
OSS ossClient = new OSSClientBuilder().build(
"https://" + ossProperties.getEndpoint(),
ossProperties.getAccessKeyId(),
ossProperties.getAccessKeySecret()
);
try {
Date expiration = new Date(System.currentTimeMillis() + 3600_000L);
URL url = ossClient.generatePresignedUrl(ossProperties.getBucket(), objectKey, expiration);
return url.toString();
} finally {
ossClient.shutdown();
}
}
}