springboot 配置访问上传图片

在 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;
    }
}

总结

  1. 开发环境 :使用 addResourceHandlers 映射本地目录
  2. 生产环境:建议使用 Nginx 直接服务静态文件,提高性能
  3. 安全性:一定要验证文件类型和大小,防止恶意文件上传
  4. 路径问题:使用绝对路径,避免相对路径带来的问题
  5. 跨平台:注意 Windows 和 Linux 的路径分隔符差异

这样就可以通过类似 http://localhost:8080/uploads/filename.jpg 的 URL 访问上传的图片了。

相关推荐
用户26851612107562 小时前
GMP 三大核心结构体字段详解
后端·go
一路向北⁢2 小时前
短信登录安全防护方案(Spring Boot)
spring boot·redis·后端·安全·sms·短信登录
古城小栈2 小时前
Tokio:Rust 异步界的 “霸主”
开发语言·后端·rust
涵涵(互关)2 小时前
JavaScript 对大整数(超过 2^53 - 1)的精度丢失问题
java·javascript·vue.js
进击的丸子2 小时前
基于虹软Linux Pro SDK的多路RTSP流并发接入、解码与帧级处理实践
java·后端·github
小北方城市网2 小时前
微服务架构设计实战指南:从拆分到落地,构建高可用分布式系统
java·运维·数据库·分布式·python·微服务
开开心心_Every2 小时前
离线黑白照片上色工具:操作简单效果逼真
java·服务器·前端·学习·edge·c#·powerpoint
予枫的编程笔记2 小时前
【Java进阶】深入浅出 Java 锁机制:从“单身公寓”到“交通管制”的并发艺术
java·人工智能·
while(1){yan}2 小时前
SpringAOP
java·开发语言·spring boot·spring·aop