完成新需求
This commit is contained in:
+37
@@ -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;
|
||||
}
|
||||
+39
@@ -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;
|
||||
}
|
||||
}
|
||||
+49
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user