更新带货视频工作流接口和页面
This commit is contained in:
+35
-2
@@ -4,6 +4,7 @@ import com.nanri.aiimage.common.api.ApiResponse;
|
||||
import com.nanri.aiimage.modules.file.model.vo.ExcelInfoVo;
|
||||
import com.nanri.aiimage.modules.file.model.vo.UploadFileVo;
|
||||
import com.nanri.aiimage.modules.file.service.LocalFileStorageService;
|
||||
import com.nanri.aiimage.modules.file.service.oss.OssStorageService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.enums.ParameterIn;
|
||||
@@ -19,6 +20,8 @@ import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@RequestMapping("/api/files")
|
||||
@@ -26,6 +29,7 @@ import org.springframework.web.multipart.MultipartFile;
|
||||
public class FileUploadController {
|
||||
|
||||
private final LocalFileStorageService localFileStorageService;
|
||||
private final OssStorageService ossStorageService;
|
||||
|
||||
@PostMapping("/upload")
|
||||
@Operation(
|
||||
@@ -47,8 +51,22 @@ public class FileUploadController {
|
||||
public ApiResponse<UploadFileVo> upload(
|
||||
@Parameter(name = "file", description = "待上传的 Excel 或业务源文件", required = true, in = ParameterIn.QUERY)
|
||||
MultipartFile file,
|
||||
@RequestParam(required = false) String relativePath) throws Exception {
|
||||
return ApiResponse.success(localFileStorageService.saveTempFile(file, relativePath));
|
||||
@RequestParam(required = false) String relativePath,
|
||||
@RequestParam(defaultValue = "false") boolean uploadToOss,
|
||||
@RequestParam(defaultValue = "COMMON") String moduleType) throws Exception {
|
||||
UploadFileVo vo = localFileStorageService.saveTempFile(file, relativePath);
|
||||
if (uploadToOss) {
|
||||
File localFile = new File(vo.getLocalPath());
|
||||
OssStorageService.UploadedResult uploaded = ossStorageService.uploadPublicFileWithFreshDownloadUrl(
|
||||
localFile,
|
||||
moduleType,
|
||||
file.getOriginalFilename()
|
||||
);
|
||||
vo.setObjectKey(uploaded.objectKey());
|
||||
vo.setUrl(uploaded.downloadUrl());
|
||||
vo.setMediaType(resolveMediaType(file.getContentType(), file.getOriginalFilename()));
|
||||
}
|
||||
return ApiResponse.success(vo);
|
||||
}
|
||||
|
||||
@GetMapping("/excel-info")
|
||||
@@ -60,4 +78,19 @@ public class FileUploadController {
|
||||
public ApiResponse<ExcelInfoVo> excelInfo(@RequestParam String fileKey) throws Exception {
|
||||
return ApiResponse.success(localFileStorageService.getExcelInfo(fileKey));
|
||||
}
|
||||
|
||||
private String resolveMediaType(String contentType, String filename) {
|
||||
String type = contentType == null ? "" : contentType.toLowerCase();
|
||||
String name = filename == null ? "" : filename.toLowerCase();
|
||||
if (type.startsWith("image/") || name.matches(".*\\.(png|jpe?g|webp|gif|bmp|svg)$")) {
|
||||
return "image";
|
||||
}
|
||||
if (type.startsWith("video/") || name.matches(".*\\.(mp4|mov|webm|m4v|ogg|avi|mkv)$")) {
|
||||
return "video";
|
||||
}
|
||||
if (type.startsWith("audio/") || name.matches(".*\\.(mp3|wav|m4a|aac|flac)$")) {
|
||||
return "audio";
|
||||
}
|
||||
return "file";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,4 +21,13 @@ public class UploadFileVo {
|
||||
|
||||
@Schema(description = "相对上传目录路径")
|
||||
private String relativePath;
|
||||
|
||||
@Schema(description = "OSS 对象 key。仅 uploadToOss=true 时返回")
|
||||
private String objectKey;
|
||||
|
||||
@Schema(description = "OSS 公网 URL。仅 uploadToOss=true 时返回")
|
||||
private String url;
|
||||
|
||||
@Schema(description = "媒体类型:image/video/audio/file。仅 uploadToOss=true 时返回")
|
||||
private String mediaType;
|
||||
}
|
||||
|
||||
+58
-1
@@ -47,6 +47,24 @@ public class OssStorageService {
|
||||
}
|
||||
}
|
||||
|
||||
public UploadedResult uploadPublicFileWithFreshDownloadUrl(File file, String moduleType, String originalFilename) {
|
||||
String normalizedModuleType = moduleType == null || moduleType.isBlank()
|
||||
? "common"
|
||||
: moduleType.trim().toLowerCase();
|
||||
String objectName = sanitizeObjectName(originalFilename);
|
||||
if (objectName.isBlank()) {
|
||||
objectName = file.getName();
|
||||
}
|
||||
String objectKey = String.format("upload/%s/%s/%s", normalizedModuleType, UUID.randomUUID(), objectName);
|
||||
OSS ossClient = buildClient();
|
||||
try {
|
||||
ossClient.putObject(ossProperties.getBucket(), objectKey, file);
|
||||
return new UploadedResult(objectKey, getPublicUrl(objectKey));
|
||||
} finally {
|
||||
ossClient.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
public String uploadText(String objectKey, String content) {
|
||||
if (objectKey == null || objectKey.isBlank()) {
|
||||
throw new IllegalArgumentException("objectKey must not be blank");
|
||||
@@ -109,6 +127,19 @@ public class OssStorageService {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean objectExists(String value) {
|
||||
String objectKey = resolveObjectKey(value);
|
||||
if (objectKey == null || objectKey.isBlank()) {
|
||||
return false;
|
||||
}
|
||||
OSS ossClient = buildClient();
|
||||
try {
|
||||
return ossClient.doesObjectExist(ossProperties.getBucket(), objectKey);
|
||||
} finally {
|
||||
ossClient.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据 objectKey 生成公开直链下载 URL。
|
||||
*/
|
||||
@@ -125,7 +156,7 @@ public class OssStorageService {
|
||||
}
|
||||
String objectKey = resolveObjectKey(value);
|
||||
String normalizedKey = objectKey.startsWith("/") ? objectKey.substring(1) : objectKey;
|
||||
String host = String.format("%s.%s", ossProperties.getBucket(), ossProperties.getEndpoint());
|
||||
String host = String.format("%s.%s", ossProperties.getBucket(), publicEndpoint());
|
||||
try {
|
||||
return new URI("https", host, "/" + normalizedKey, null).toASCIIString();
|
||||
} catch (Exception ignored) {
|
||||
@@ -179,6 +210,32 @@ public class OssStorageService {
|
||||
);
|
||||
}
|
||||
|
||||
private String publicEndpoint() {
|
||||
String endpoint = ossProperties.getPublicEndpoint();
|
||||
if (endpoint == null || endpoint.isBlank()) {
|
||||
endpoint = ossProperties.getEndpoint();
|
||||
}
|
||||
endpoint = endpoint.trim();
|
||||
if (endpoint.startsWith("http://")) {
|
||||
endpoint = endpoint.substring("http://".length());
|
||||
} else if (endpoint.startsWith("https://")) {
|
||||
endpoint = endpoint.substring("https://".length());
|
||||
}
|
||||
return endpoint.endsWith("/") ? endpoint.substring(0, endpoint.length() - 1) : endpoint;
|
||||
}
|
||||
|
||||
private String sanitizeObjectName(String filename) {
|
||||
if (filename == null || filename.isBlank()) {
|
||||
return "";
|
||||
}
|
||||
String normalized = filename.trim().replace('\\', '/');
|
||||
int slashIndex = normalized.lastIndexOf('/');
|
||||
if (slashIndex >= 0 && slashIndex + 1 < normalized.length()) {
|
||||
normalized = normalized.substring(slashIndex + 1);
|
||||
}
|
||||
return normalized.replaceAll("[\\r\\n]", "_");
|
||||
}
|
||||
|
||||
public record UploadedResult(String objectKey, String downloadUrl) {
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user