您现在的位置是:首页 >技术杂谈 >7.2 SpringBoot实现上传图片API + url映射本地路径registry.addResourceHandler网站首页技术杂谈

7.2 SpringBoot实现上传图片API + url映射本地路径registry.addResourceHandler

天罡gg 2024-05-09 00:00:02
简介7.2 SpringBoot实现上传图片API + url映射本地路径registry.addResourceHandler

CSDN成就一亿技术人


前言

在图书借阅系统里,有很多图片需要前端展示,这些图片大都是由用户上传,保存在服务端,所以服务端需要提供上传和访问图片
基本要求:前端直接访问网络图片url 就可以打开图片,不用下载,更不用base64转码!

实现方式

  1. Tomcat静态目录,需要单独部署Tomcat,你只需要把图片保存到Tomcat静态目录
  2. SpringBoot添加url映射本地路径,和Tomcat静态目录很像,需要重写WebMvcConfigurer的addResourceHandlers,并registry.addResourceHandler(添加url映射本地路径),同样只需要把图片保存到本地路径即可。
  3. 云对象存储(像oss,cos等),功能丰富,提供加密、裁剪等等很多功能,可以保存各种文件,需要对接API,收费
  4. 图床,专门保存图片,需要对接API

因为我们是基于SpringBoot开发,所以选择方案2,最终的效果:例如访问http://localhost:8080/files/图书借阅系统一期SpringBoot-天罡gg.png,实际是访问E:projectsfiles图书借阅系统一期SpringBoot-天罡gg.png。(window和linux环境原理相同)

在这里插入图片描述

所以,主要实现的是「url映射本地路径」和「上传图片API」,OK,要做的事情说清楚了,接下来实现!


一、url映射本地路径

这是本文的重点!重写WebMvcConfigurer的addResourceHandlers方法。

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
    registry.addResourceHandler(uploadResourceHandler+"/**").addResourceLocations("file:" + uploadResourceLocation);
}

uploadResourceHandler和uploadResourceLocation,由于window和linux路径不成,所以都做成了配置,从配置文件application.properties读取:

// 上传文件的请求路径
@Value("${upload.resource.handler}")
private String uploadResourceHandler;
// 上传文件的映射本地路径
@Value("${upload.resource.location}")
private String uploadResourceLocation;

配置文件application.properties添加配置:

upload.resource.handler=/files
upload.resource.location=E:/projects/files/

另外,拦截器里要排除uploadResourceHandler路径,否则需要登录才能访问。代码融合到了InterceptorConfig类,完整代码如下:

@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
    @Autowired
    private AuthInterceptor authInterceptor;
    // 上传文件的请求路径
    @Value("${upload.resource.handler}")
    private String uploadResourceHandler;
    // 上传文件的映射本地路径
    @Value("${upload.resource.location}")
    private String uploadResourceLocation;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 身份认证拦截器
        registry.addInterceptor(authInterceptor)
                .addPathPatterns("/**")
                // 排除的请求路径
                .excludePathPatterns("/auth/login", "/auth/register", "/auth/test/cors", uploadResourceHandler+"/**");
    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler(uploadResourceHandler+"/**").addResourceLocations("file:" + uploadResourceLocation);
    }
}

这时,你也可以手动把图片放到目录E:/projects/files/中,然后通过 http://localhost:8080/files/xxx.png 就可以正常访问了~???


二、上传图片API

2.1 接口UploadService

在service层增加

public interface UploadService {
    String uploadImage(MultipartFile file);
}

2.2 实现类UploadServiceImpl

在service层的impl包下增加
思路很简单,将图片文件MultipartFile上传到映射的本地路径uploadResourceLocation。
分3步:

  1. 定义文件名:fileName,使用UUID(防止覆盖)+原始文件的扩展名
  2. 将上传的file保存到saveFile, 也就是映射的本地路径uploadResourceLocation
  3. 返回前端可访问的网络地址,这里新增了一个配置upload.host,定义服务器地址
@Service
@Slf4j
public class UploadServiceImpl implements UploadService {
    @Value("${upload.host}")
    private String uploadHost;
    // 上传文件的请求路径
    @Value("${upload.resource.handler}")
    private String uploadResourceHandler;
    // 上传文件的映射本地路径
    @Value("${upload.resource.location}")
    private String uploadResourceLocation;

    @Override
    public String uploadImage(MultipartFile file) {
        // 1.定义文件名:fileName,使用UUID(防止覆盖)+原始文件的扩展名
        String fileName = UUID.randomUUID().toString();
        String originalFilename = file.getOriginalFilename();
        if (originalFilename != null && originalFilename.lastIndexOf(".") >= 0) {
            fileName += file.getOriginalFilename().substring(originalFilename.lastIndexOf("."));
        } else {
            fileName += ".png";
        }
        // 2. 将上传的file保存到saveFile, 也就是映射的本地路径uploadResourceLocation
        File saveFile = new File(uploadResourceLocation, fileName);
        try {
            file.transferTo(saveFile);
        } catch (IOException e) {
            log.error("图片上传失败:{}", e.getMessage(), e);
        }
        // 3. 返回前端可访问的网络地址
        return uploadHost + uploadResourceHandler + "/" + fileName;
    }
}

对于log,后面加上e会打印出详细的堆栈信息。

2.3 上传图片Controller

在controller包下定义UploadController,注入UploadService
文件使用MultipartFile类,Post请求,其它应该都轻车熟路了,不做赘述!

@RestController
@RequestMapping("/upload")
public class UploadController {

    @Autowired
    private UploadService uploadService;

    @PostMapping("/image")
    public TgResult<String> uploadImage(@RequestParam(value = "file") MultipartFile file) {
        //判断文件是否为空
        if (file.isEmpty()) {
            return TgResult.fail("400", "上传图片不能为空");
        }
        String url = uploadService.uploadImage(file);
        return TgResult.ok(url);
    }
}

配置文件application.properties共添加3个配置:

upload.host=http://localhost:8080
upload.resource.handler=/files
upload.resource.location=E:/projects/files/

三、测试

通过Postman调用上传图片API
在这里插入图片描述
将返回的结果用浏览器直接打开如下:
在这里插入图片描述


最后

想要看更多实战好文章,还是给大家推荐我的实战专栏–>《基于SpringBoot+SpringCloud+Vue前后端分离项目实战》,由我和 前端狗哥 合力打造的一款专栏,可以让你从0到1快速拥有企业级规范的项目实战经验!

具体的优势、规划、技术选型都可以在《开篇》试读!

博主保证会用心持续高质量输出文章哦!

订阅专栏后也可以添加博主的微信,博主会为每一位用户进行针对性指导!

另外,别忘了关注我:天罡gg ,发布新文不容易错过: https://blog.csdn.net/scm_2008

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。