Spring Boot应用实现图片资源服务的方法

 更新时间:2025年08月20日 11:09:15   作者:QingyunChen  
本文介绍如何使用SpringBoot创建REST API提供静态图片服务,涵盖路径安全检查、文件存在性验证及缓存控制功能,包含Maven依赖配置和代码注释,帮助开发者实现安全高效的图片资源访问,感兴趣的朋友跟随小编一起看看吧

在这篇文章中,我们将介绍如何使用Spring Boot创建一个REST API来提供服务器上的静态图片资源。该API包括路径安全检查、文件存在性验证以及缓存控制等功能,并且代码包含详细的注释以帮助理解。

Maven依赖

首先,在您的pom.xml文件中添加以下依赖项:

<dependencies>
    <!-- Spring Boot Starter Web for building web applications -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!-- Lombok to reduce boilerplate code -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <scope>provided</scope>
    </dependency>
    <!-- For logging -->
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
    </dependency>
</dependencies>

确保您已经正确配置了Maven项目的其他部分,如<parent>标签和版本管理等。

Java代码

接下来是核心Java代码,位于package pub.qingyun.web;包下:

package pub.qingyun.web;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.UrlResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.net.MalformedURLException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
@RestController
@CrossOrigin
@Slf4j
public class ImageController {
    // 图片根目录
    private static final Path IMAGE_ROOT = Paths.get("F:", "Temp").toAbsolutePath().normalize();
    /**
     * 获取图片资源并返回给客户端
     *
     * @param imagePath 图片文件的相对路径参数
     * @return ResponseEntity<UrlResource> 包含图片资源的响应实体,包含适当的HTTP状态码和响应头
     */
    @GetMapping("/showImage")
    public ResponseEntity<UrlResource> getImage(@RequestParam String imagePath) {
        long start = System.currentTimeMillis();
        // 参数校验:检查图片路径是否为空
        if (imagePath == null || imagePath.trim().isEmpty()) {
            log.warn("Missing imagePath parameter");
            return ResponseEntity.badRequest().build();
        }
        // 路径安全检查:防止路径遍历攻击
        // 过滤非法字符,防止路径穿越
        if (imagePath.contains("..") || imagePath.contains("\\") || imagePath.startsWith("/")) {
            log.warn("Forbidden path access attempt: [PATH_REDACTED]");
            return ResponseEntity.status(403).build();
        }
        Path resolvedPath = IMAGE_ROOT.resolve(imagePath).normalize();
        if (!resolvedPath.startsWith(IMAGE_ROOT)) {
            log.warn("Forbidden path access attempt: [PATH_REDACTED]");
            return ResponseEntity.status(403).build();
        }
        // 文件存在性检查:验证文件是否存在且为常规文件
        if (!Files.exists(resolvedPath) || !Files.isRegularFile(resolvedPath)) {
            log.info("Image not found: [PATH_REDACTED]");
            return ResponseEntity.notFound().build();
        }
        // 缓存文件长度,避免重复调用
        long fileLength = resolvedPath.toFile().length();
        // 创建资源对象
        UrlResource resource;
        try {
            resource = new UrlResource(resolvedPath.toUri());
        } catch (MalformedURLException e) {
            log.error("Failed to create resource for: [PATH_REDACTED], Malformed URL", e);
            return ResponseEntity.status(500).build();
        } catch (Exception e) {
            log.error("Failed to create resource for: [PATH_REDACTED]", e);
            return ResponseEntity.status(500).build();
        }
        // 设置响应头信息
        HttpHeaders headers = new HttpHeaders();
        headers.setCacheControl("public, max-age=86400"); // 缓存 1 天
        headers.setExpires(System.currentTimeMillis() + 86400_000L); // 过期时间
        headers.setContentDispositionFormData("inline", resource.getFilename());
        log.info("getImage [PATH_REDACTED] ({} bytes) cost: {}ms", fileLength, (System.currentTimeMillis() - start));
        // 构建并返回成功响应
        return ResponseEntity.ok()
                .headers(headers)
                .contentType(MediaType.IMAGE_JPEG)
                .contentLength(fileLength)
                .body(resource);
    }
}

这个代码段展示了一个简单的Spring Boot REST控制器,用于从指定路径加载图片并将其作为资源返回给客户端。它包括必要的安全措施来防止潜在的路径遍历攻击,并设置了缓存控制头以提高性能。希望这段代码能为您提供构建自己的图片服务的帮助!

到此这篇关于Spring Boot应用实现图片资源服务的文章就介绍到这了,更多相关Spring Boot图片资源服务内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java序列化和反序列化_动力节点Java学院整理

    Java序列化和反序列化_动力节点Java学院整理

    把对象转换为字节序列的过程称为对象的序列化,把字节序列恢复为对象的过程称为对象的反序列化。接下来通过本文给大家介绍Java序列化和反序列化及主要的两种用途,感兴趣的的友参考下吧
    2017-05-05
  • 存储过程创建及springboot代码调用存储过程方式

    存储过程创建及springboot代码调用存储过程方式

    文章介绍了如何在Navicat中创建存储过程,并在Spring Boot项目中调用存储过程,存储过程创建步骤包括选择函数类型、自定义函数名、添加参数等,在Spring Boot中调用存储过程时,可以通过JdbcTemplate或MyBatis等工具进行
    2024-11-11
  • 一文详解Java中的动态填充Html模版并转PDF

    一文详解Java中的动态填充Html模版并转PDF

    在后端技术中,模板引擎和PDF生成工具是两个非常重要的领域,Thymeleaf和wkhtmltopdf是这两个领域的杰出代表,下面就来详细介绍一下Thymeleaf和wkhtmltopdf的技术特点吧
    2023-12-12
  • 一文详解Java如何系统地避免空指针问题

    一文详解Java如何系统地避免空指针问题

    新手Java开发总是经常空指针检查,甚至某些老手也会犯这样的问题,所以这篇文章小编就带大家一起来看看如何系统地避免空指针问题,希望对大家有所帮助
    2024-01-01
  • springboot 静态方法中使用@Autowired注入方式

    springboot 静态方法中使用@Autowired注入方式

    这篇文章主要介绍了springboot 静态方法中使用@Autowired注入方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-02-02
  • Mybatis-plus批量插入的2种方式总结

    Mybatis-plus批量插入的2种方式总结

    这篇文章主要给大家总结介绍了关于Mybatis-plus批量插入的2种方式,Mybatis-Plus提供了多种方式进行批量插入优化,文中通过代码示例将实现的方法介绍的非常详细,需要的朋友可以参考下
    2023-08-08
  • Java Mybatis框架由浅入深全解析上篇

    Java Mybatis框架由浅入深全解析上篇

    MyBatis是一个优秀的持久层框架,它对jdbc的操作数据库的过程进行封装,使开发者只需要关注SQL本身,而不需要花费精力去处理例如注册驱动、创建connection、创建statement、手动设置参数、结果集检索等jdbc繁杂的过程代码本文将为大家初步的介绍一下MyBatis的使用
    2022-07-07
  • 理解Java注解及Spring的@Autowired是如何实现的

    理解Java注解及Spring的@Autowired是如何实现的

    今天通过本文带领大家学习注解的基础知识,学习Spring的@Autowired是怎么实现的,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2021-07-07
  • 使用Hutool编写生成随机数的工具类

    使用Hutool编写生成随机数的工具类

    Hutool 是一个 Java 工具类库,提供了丰富的工具方法,其中 RandomUtil 是 Hutool 中用于生成随机数的工具类,下面我们来看看它的具体使用吧
    2025-02-02
  • Java使用正则表达式删除所有HTML标签的方法示例

    Java使用正则表达式删除所有HTML标签的方法示例

    这篇文章主要介绍了Java使用正则表达式删除所有HTML标签的方法,结合完整实例形式分析了java针对HTML页面元素script标签、style标签、html标签等的正则匹配相关操作技巧,需要的朋友可以参考下
    2017-06-06

最新评论