文件存储
文件上传
java
@RestController
@RequestMapping("/api/files")
public class FileController {
@Value("${upload.path:/tmp}")
private String uploadPath; // 上传目录,可从配置读取
@PostMapping("/upload")
public String upload(@RequestParam("file") MultipartFile file) {
// 类比 PHP 的 $request->file('file')
String originalName = file.getOriginalFilename(); // 原始文件名
String contentType = file.getContentType(); // MIME 类型
long size = file.getSize(); // 文件大小(字节)
// 生成唯一文件名
String ext = originalName.substring(originalName.lastIndexOf("."));
String savedName = UUID.randomUUID() + ext;
try {
// 保存到本地
file.transferTo(new File(uploadPath + "/" + savedName));
return savedName;
} catch (IOException e) {
throw new RuntimeException("文件上传失败", e);
}
}
@PostMapping("/uploads")
public List<String> uploadMultiple(
@RequestParam("files") List<MultipartFile> files) { // 多文件
List<String> names = new ArrayList<>();
for (MultipartFile file : files) {
// ... 保存每个文件
}
return names;
}
}PHP 中
$request->file('avatar')->store('avatars')一行完成。Java 需要手动处理文件名、保存路径、异常。原因:Laravel 的文件系统是高度封装的——本地用
storage/app/,云存储用 S3,API 统一。Spring Boot 的MultipartFile是原始接口,没有 Laravel 那种Filesystem抽象层。
文件下载
java
@GetMapping("/download/{name}")
public ResponseEntity<Resource> download(@PathVariable String name) {
try {
Path file = Paths.get(uploadPath).resolve(name);
Resource resource = new UrlResource(file.toUri());
if (!resource.exists() || !resource.isReadable()) {
return ResponseEntity.notFound().build();
}
return ResponseEntity.ok()
.contentType(MediaType.APPLICATION_OCTET_STREAM)
.header(HttpHeaders.CONTENT_DISPOSITION,
"attachment; filename=\"" + resource.getFilename() + "\"")
.body(resource);
} catch (IOException e) {
return ResponseEntity.internalServerError().build();
}
}静态资源
Spring Boot 默认将以下目录映射为静态资源路径:
src/main/resources/static/ → http://localhost:8080/css/app.css
src/main/resources/public/ → http://localhost:8080/js/app.js
src/main/resources/resources/ → http://localhost:8080/images/logo.png类比 Laravel 的
public/目录。Spring Boot 中叫static/,内容一样——放 CSS、JS、图片等。
yaml
# 自定义静态资源路径
spring:
web:
resources:
static-locations: classpath:/static/, file:/opt/assets/
# ⬆ 可以是 classpath 或文件系统路径⚠️ 常见坑
1. Multipart 文件大小限制
默认最大 1MB,超过报错:
MaxUploadSizeExceededExceptionyamlspring: servlet: multipart: max-file-size: 10MB # 单个文件大小 max-request-size: 50MB # 单次请求总大小
2. 文件路径分隔符
java// Windows 下 File.separator 是 \,Linux 是 / // 用 Paths.get() 自动处理 Path path = Paths.get(uploadPath, savedName); // ✅ 跨平台安全 // 不要手动拼接字符串 File f = new File(uploadPath + "/" + savedName); // ❌ Windows 下可能出问题
3. 临时文件删除
MultipartFile.transferTo()完成后,临时文件会自动删除。如果你在transferTo()之前读了文件内容,需要自己确保临时目录的清理。
4. 没有 Laravel 的 Filesystem 抽象
Laravel 的
Storage::disk('s3')->put(...)可以无缝切换本地和云存储。Spring Boot 没有这样的内置抽象,需要自己封装或使用第三方库(如 AWS SDK)。如果只是本地存储,直接用
MultipartFile.transferTo()就够。如果需要 S3,加上spring-cloud-starter-aws依赖。