package com.designhub.controller; import com.designhub.common.Result; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import jakarta.annotation.PostConstruct; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.*; /** * 文件上传Controller */ @Slf4j @RestController @RequestMapping("/api/upload") @Tag(name = "文件上传", description = "文件上传相关API") public class UploadController { @Value("${file.upload.path:./uploads}") private String uploadPath; @Value("${file.upload.max-size:52428800}") private long maxSize; @Value("${file.upload.allowed-extensions:.xls,.xlsx,.doc,.docx,.pdf,.zip}") private String allowedExtensions; private static final Set ALLOWED_EXTENSIONS_SET = new HashSet<>(); @PostConstruct public void init() { String[] extensions = allowedExtensions.split(","); for (String ext : extensions) { ALLOWED_EXTENSIONS_SET.add(ext.trim().toLowerCase()); } // 确保上传目录存在 try { Path path = Paths.get(uploadPath); if (!Files.exists(path)) { Files.createDirectories(path); log.info("创建上传目录: {}", uploadPath); } } catch (IOException e) { log.error("创建上传目录失败: {}", e.getMessage()); } } /** * 上传文件 */ @PostMapping("/file") @Operation(summary = "上传文件", description = "支持Excel、Word、PDF、ZIP等格式") public Result> uploadFile(@RequestParam("file") MultipartFile file) { try { // 验证文件 if (file == null || file.isEmpty()) { return Result.error(400, "文件不能为空"); } // 验证文件大小 if (file.getSize() > maxSize) { return Result.error(400, String.format("文件大小不能超过 %d MB", maxSize / 1024 / 1024)); } // 验证文件扩展名 String originalFilename = file.getOriginalFilename(); if (originalFilename == null || originalFilename.isEmpty()) { return Result.error(400, "文件名不能为空"); } String extension = getFileExtension(originalFilename); if (!ALLOWED_EXTENSIONS_SET.contains(extension.toLowerCase())) { return Result.error(400, String.format("不支持的文件格式,支持的格式:%s", allowedExtensions)); } // 生成文件存储路径 String dateDir = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy/MM/dd")); String fileName = generateFileName(originalFilename); String relativePath = dateDir + "/" + fileName; String fullPath = uploadPath + "/" + relativePath; // 确保目录存在 Path targetPath = Paths.get(fullPath); Files.createDirectories(targetPath.getParent()); // 保存文件 file.transferTo(targetPath.toFile()); log.info("文件上传成功: originalName={}, savedPath={}, size={}", originalFilename, fullPath, file.getSize()); // 构建返回数据 Map data = new HashMap<>(); data.put("fileName", originalFilename); data.put("filePath", relativePath); data.put("fileUrl", "/api/upload/download?path=" + relativePath); data.put("fileSize", file.getSize()); data.put("fileType", extension); return Result.success(data); } catch (IOException e) { log.error("文件上传失败: {}", e.getMessage(), e); return Result.error(500, "文件上传失败: " + e.getMessage()); } catch (Exception e) { log.error("文件上传异常: {}", e.getMessage(), e); return Result.error(500, "文件上传异常: " + e.getMessage()); } } /** * 下载文件 */ @GetMapping("/download") @Operation(summary = "下载文件", description = "根据文件路径下载文件") public org.springframework.http.ResponseEntity downloadFile( @RequestParam("path") String filePath) { try { String fullPath = uploadPath + "/" + filePath; Path path = Paths.get(fullPath); if (!Files.exists(path)) { return org.springframework.http.ResponseEntity.notFound().build(); } org.springframework.core.io.Resource resource = new org.springframework.core.io.UrlResource(path.toUri()); return org.springframework.http.ResponseEntity.ok() .header(org.springframework.http.HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + resource.getFilename() + "\"") .body(resource); } catch (Exception e) { log.error("文件下载失败: {}", e.getMessage(), e); return org.springframework.http.ResponseEntity.internalServerError().build(); } } /** * 获取文件扩展名 */ private String getFileExtension(String filename) { int lastDotIndex = filename.lastIndexOf('.'); if (lastDotIndex > 0 && lastDotIndex < filename.length() - 1) { return filename.substring(lastDotIndex); } return ""; } /** * 生成唯一文件名 */ private String generateFileName(String originalFilename) { String extension = getFileExtension(originalFilename); String nameWithoutExt = originalFilename.substring(0, originalFilename.lastIndexOf('.')); String timestamp = String.valueOf(System.currentTimeMillis()); String random = UUID.randomUUID().toString().substring(0, 8); return nameWithoutExt + "_" + timestamp + "_" + random + extension; } }