| | |
| | | import org.springframework.web.bind.annotation.RequestParam; |
| | | import org.springframework.web.bind.annotation.RestController; |
| | | import org.springframework.web.multipart.MultipartFile; |
| | | import org.springframework.util.StringUtils; |
| | | |
| | | import java.io.IOException; |
| | | import java.util.Arrays; |
| | |
| | | |
| | | private static final long MAX_SIZE = 5 * 1024 * 1024L; // 5MB |
| | | private static final long VIDEO_MAX_SIZE = 200 * 1024 * 1024L; // 200MB |
| | | private static final long APP_PACKAGE_MAX_SIZE = 500 * 1024 * 1024L; // 500MB |
| | | private static final Set<String> ALLOWED_TYPES = new HashSet<>( |
| | | Arrays.asList("image/jpeg", "image/png", "image/gif", "image/webp") |
| | | ); |
| | | private static final Set<String> ALLOWED_VIDEO_TYPES = new HashSet<>( |
| | | Arrays.asList("video/mp4", "video/quicktime", "video/x-msvideo", "video/x-matroska", "video/webm") |
| | | ); |
| | | private static final Set<String> ALLOWED_APP_PACKAGE_TYPES = new HashSet<>( |
| | | Arrays.asList( |
| | | "application/vnd.android.package-archive", |
| | | "application/octet-stream", |
| | | "application/x-itunes-ipa", |
| | | "application/zip", |
| | | "application/x-zip-compressed" |
| | | ) |
| | | ); |
| | | private static final String PLATFORM_ANDROID = "ANDROID"; |
| | | private static final String PLATFORM_IOS = "IOS"; |
| | | |
| | | private final ObsUploadService obsUploadService; |
| | | private final UploadProgressService uploadProgressService; |
| | |
| | | return ApiResponse.ok(storeFile(file, VIDEO_MAX_SIZE, ALLOWED_VIDEO_TYPES, "仅支持 MP4、MOV、AVI、MKV、WebM 格式", "video", uploadTaskId)); |
| | | } |
| | | |
| | | @PostMapping("/upload/app-package") |
| | | public ApiResponse<UploadResult> uploadAppPackage( |
| | | @RequestParam("file") MultipartFile file, |
| | | @RequestParam("platform") String platform) throws IOException { |
| | | String normalizedPlatform = normalizePlatform(platform); |
| | | validateAppPackage(file, normalizedPlatform); |
| | | UploadFileResult uploadResult = obsUploadService.upload(file, "app-package/" + normalizedPlatform.toLowerCase(), null); |
| | | return ApiResponse.ok(new UploadResult(uploadResult.getUrl(), uploadResult.getFileName())); |
| | | } |
| | | |
| | | @GetMapping("/upload/video/progress") |
| | | public ApiResponse<UploadProgressInfo> uploadVideoProgress( |
| | | @RequestParam("taskId") String taskId) { |
| | |
| | | String typeMessage, |
| | | String bizPath, |
| | | String uploadTaskId) throws IOException { |
| | | if (file == null || file.isEmpty()) { |
| | | throw new IllegalArgumentException("请选择要上传的文件"); |
| | | } |
| | | if (file.getSize() > maxSize) { |
| | | throw new IllegalArgumentException("文件大小超出限制"); |
| | | } |
| | | validateFileSize(file, maxSize); |
| | | String contentType = file.getContentType(); |
| | | if (contentType == null || !allowedTypes.contains(contentType)) { |
| | | throw new IllegalArgumentException(typeMessage); |
| | |
| | | return new UploadResult(uploadResult.getUrl(), uploadResult.getFileName()); |
| | | } |
| | | |
| | | private void validateFileSize(MultipartFile file, long maxSize) { |
| | | if (file == null || file.isEmpty()) { |
| | | throw new IllegalArgumentException("请选择要上传的文件"); |
| | | } |
| | | if (file.getSize() > maxSize) { |
| | | throw new IllegalArgumentException("文件大小超出限制"); |
| | | } |
| | | } |
| | | |
| | | private void validateAppPackage(MultipartFile file, String platform) { |
| | | validateFileSize(file, APP_PACKAGE_MAX_SIZE); |
| | | String originalName = file.getOriginalFilename(); |
| | | String extension = ""; |
| | | if (StringUtils.hasText(originalName) && originalName.contains(".")) { |
| | | extension = originalName.substring(originalName.lastIndexOf(".") + 1).toLowerCase(); |
| | | } |
| | | if (PLATFORM_ANDROID.equals(platform) && !"apk".equals(extension)) { |
| | | throw new IllegalArgumentException("安卓安装包仅支持 APK 格式"); |
| | | } |
| | | if (PLATFORM_IOS.equals(platform) && !"ipa".equals(extension)) { |
| | | throw new IllegalArgumentException("iOS 安装包仅支持 IPA 格式"); |
| | | } |
| | | String contentType = file.getContentType(); |
| | | if (StringUtils.hasText(contentType) && !ALLOWED_APP_PACKAGE_TYPES.contains(contentType)) { |
| | | throw new IllegalArgumentException("安装包格式不合法"); |
| | | } |
| | | } |
| | | |
| | | private String normalizePlatform(String platform) { |
| | | if (!StringUtils.hasText(platform)) { |
| | | throw new IllegalArgumentException("平台类型不能为空"); |
| | | } |
| | | String normalized = platform.trim().toUpperCase(); |
| | | if (PLATFORM_ANDROID.equals(normalized) || PLATFORM_IOS.equals(normalized)) { |
| | | return normalized; |
| | | } |
| | | throw new IllegalArgumentException("平台类型不合法"); |
| | | } |
| | | |
| | | public static class UploadResult { |
| | | private final String url; |
| | | private final String fileName; |