172 lines
6.3 KiB
Java
172 lines
6.3 KiB
Java
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<String> 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<Map<String, Object>> 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<String, Object> 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<org.springframework.core.io.Resource> 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;
|
|
}
|
|
}
|
|
|