在 Spring Boot 中配置访问上传的图片,主要有两种方式:
1. 配置静态资源访问
方式一:WebMvcConfigurer 配置类
java
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// 访问路径 对应本地目录
registry.addResourceHandler("/uploads/**")
.addResourceLocations("file:D:/uploads/");
// 或者使用 classpath: 前缀访问项目内的文件
}
}
方式二:application.yml/properties 配置
yaml
spring:
web:
resources:
static-locations: classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/,file:${upload.path}
upload:
path: D:/uploads/ # 或者使用绝对路径
2. 完整的上传和访问示例
2.1 配置文件
yaml
# application.yml
server:
port: 8080
spring:
servlet:
multipart:
max-file-size: 10MB
max-request-size: 10MB
upload:
path: ${user.home}/uploads/ # 使用系统用户目录
2.2 配置类
java
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Value("${upload.path}")
private String uploadPath;
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// 确保目录存在
File uploadDir = new File(uploadPath);
if (!uploadDir.exists()) {
uploadDir.mkdirs();
}
// 配置静态资源映射
registry.addResourceHandler("/uploads/**")
.addResourceLocations("file:" + uploadPath + "/");
}
}
2.3 文件上传控制器
java
@RestController
@RequestMapping("/api/file")
public class FileUploadController {
@Value("${upload.path}")
private String uploadPath;
@PostMapping("/upload")
public ApiResult upload(@RequestParam("file") MultipartFile file) {
try {
if (file.isEmpty()) {
return ApiResult.error("文件不能为空");
}
// 生成唯一文件名
String originalFilename = file.getOriginalFilename();
String extension = originalFilename.substring(originalFilename.lastIndexOf("."));
String filename = UUID.randomUUID() + extension;
// 保存文件
File dest = new File(uploadPath + filename);
file.transferTo(dest);
// 返回访问URL
String url = "/uploads/" + filename;
return ApiResult.ok("上传成功", Map.of("url", url, "filename", filename));
} catch (Exception e) {
return ApiResult.error("上传失败: " + e.getMessage());
}
}
}
3. 进阶配置:支持跨域和更多功能
3.1 完整配置类
java
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Value("${upload.path}")
private String uploadPath;
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// 上传文件的静态资源映射
registry.addResourceHandler("/uploads/**")
.addResourceLocations("file:" + uploadPath + "/")
.setCachePeriod(3600) // 缓存1小时
.resourceChain(true)
.addResolver(new PathResourceResolver());
// 如果需要,可以添加其他静态资源映射
registry.addResourceHandler("/static/**")
.addResourceLocations("classpath:/static/");
}
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/uploads/**")
.allowedOrigins("*")
.allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS")
.allowCredentials(false)
.maxAge(3600);
}
}
3.2 图片压缩和预览接口
java
@RestController
@RequestMapping("/api/image")
public class ImageController {
@Value("${upload.path}")
private String uploadPath;
/**
* 获取图片(可缩略图)
*/
@GetMapping("/{filename}")
public void getImage(@PathVariable String filename,
@RequestParam(required = false) Integer width,
@RequestParam(required = false) Integer height,
HttpServletResponse response) throws IOException {
File imageFile = new File(uploadPath + filename);
if (!imageFile.exists()) {
response.setStatus(HttpStatus.NOT_FOUND.value());
return;
}
response.setContentType("image/jpeg");
if (width != null && height != null) {
// 生成缩略图
try (InputStream is = new FileInputStream(imageFile);
OutputStream os = response.getOutputStream()) {
Thumbnails.of(is)
.size(width, height)
.outputFormat("jpg")
.toOutputStream(os);
}
} else {
// 返回原图
Files.copy(imageFile.toPath(), response.getOutputStream());
}
}
}
4. Docker 部署配置
4.1 创建 Dockerfile
dockerfile
FROM openjdk:11-jre-slim
VOLUME /tmp
VOLUME /uploads
COPY target/your-app.jar app.jar
ENTRYPOINT ["java", "-jar", "/app.jar"]
4.2 修改 application.yml 用于 Docker
yaml
upload:
path: /uploads/
spring:
web:
resources:
static-locations: classpath:/static/,file:${upload.path}
5. 安全注意事项
5.1 文件上传安全检查
java
@Component
public class FileUploadValidator {
private static final List<String> ALLOWED_EXTENSIONS =
Arrays.asList(".jpg", ".jpeg", ".png", ".gif", ".bmp");
private static final long MAX_SIZE = 10 * 1024 * 1024; // 10MB
public boolean validate(MultipartFile file) {
// 检查文件大小
if (file.getSize() > MAX_SIZE) {
return false;
}
// 检查文件扩展名
String originalFilename = file.getOriginalFilename();
if (originalFilename == null) {
return false;
}
String extension = originalFilename.substring(
originalFilename.lastIndexOf(".")).toLowerCase();
return ALLOWED_EXTENSIONS.contains(extension);
}
}
6. Nginx 反向代理配置
nginx
server {
listen 80;
server_name yourdomain.com;
# 静态文件由 Nginx 直接处理
location /uploads/ {
alias /path/to/upload/directory/;
expires 30d;
access_log off;
}
# API 请求转发到 Spring Boot
location / {
proxy_pass http://localhost:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
总结
- 开发环境 :使用
addResourceHandlers映射本地目录 - 生产环境:建议使用 Nginx 直接服务静态文件,提高性能
- 安全性:一定要验证文件类型和大小,防止恶意文件上传
- 路径问题:使用绝对路径,避免相对路径带来的问题
- 跨平台:注意 Windows 和 Linux 的路径分隔符差异
这样就可以通过类似 http://localhost:8080/uploads/filename.jpg 的 URL 访问上传的图片了。