springboot项目中javaweb上传了图片或文件,但是图片文件无法访问,出现404页面,甚至出现报错

这篇真的是笔者花了两个小时总结的经验,都快想吐槽谁写的史山代码 [其实一年前自己写的],今天就奇了怪了,因为我想在不同环境或者主机的时候不用手动重写自己的绝对映射路径也能正常运行静态资源访问的操作。 但是但是!springboot项目中上传了图片,但是图片无法访问,出现404页面,甚至出现报错。

如果你静态资源映射配置这部分正确,图片文件读写也正确,那你就要考虑组合的问题了,这里不考虑图片文件读写的路径错误,统一用/static/face_img/加文件名的字符串

这是以前敲的:

静态资源映射配置(系统文件绝对路径):

java 复制代码
//静态资源static映射
@Configuration
public class FileUploadConfig implements WebMvcConfigurer {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/static/face_img/**")
                .addResourceLocations("file:C:\\Users\\ASUS\\Desktop\\中间省略\\static\\face_img\\");
    }

}

文件读写操作:

java 复制代码
  String filename = file.getOriginalFilename();
  String mysqlfilename = "/static/face_img/" + filename;
  // 存放上传图片的文件夹
  File fileDir = ATimelineController.UploadUtils.getImgDirFile();
  // 输出文件夹绝对路径
  try {
  System.out.println(fileDir.getAbsolutePath() + File.separator + filename);
  // 构建真实的文件路径
  File newFile = new File(fileDir.getAbsolutePath() + File.separator + filename);
  System.out.println(newFile);
  // 上传图片到绝对路径
  file.transferTo(newFile);
   } catch (IOException e) {
          e.printStackTrace();
   }


//构建上传图片的文件夹
static class UploadUtils{
// 项目根路径下的目录  -- SpringBoot static 目录相当于是根路径下(SpringBoot 默认)
public final static String IMG_PATH_PREFIX = "static/face_img";

public static File getImgDirFile(){

   // 构建上传文件的存放 "文件夹" 路径
      String fileDirPath = new String("src/main/resources/" + IMG_PATH_PREFIX);
       File fileDir = new File(fileDirPath);
        if(!fileDir.exists()){
                // 递归生成文件夹
                fileDir.mkdirs();
         }
            return fileDir;
      }
}

而我想把静态资源配置改成classpath这种方式,这时候就来聊一下这两个的区别

相同的点: 都是用了WebMvcConfigurer配置
不同的点:

区别在于资源的存储位置。

第一个配置方式使用了文件系统的绝对路径作为资源的存储位置:

.addResourceLocations("file:C:\\Users\\ASUS\\Desktop\\这里中间省略\\static\\face_img\\")

这意味着你的图片实际上是存储在你的本地文件系统中的特定路径下。这种方式的好处是你可以直接在文件系统中管理这些资源,但是缺点是如果你的应用部署到其他环境中,可能会导致资源路径失效或者不可访问。

第二个配置方式使用了classpath作为资源的存储位置:

.addResourceLocations("classpath:/static/face_img/")

这意味着你的图片资源被打包到了你的应用的classpath中。这种方式的好处是你的应用可以在不同环境中移植而不用担心资源路径的问题,但是缺点是你不能直接在文件系统中管理这些资源,需要通过重新打包应用来更新资源。

我想让我的应用可以在不同环境中移植而不用担心资源路径的问题,所以想改成第二种配置方式。

但是,文件读写也要同步改,因为原先写入的图片路径是源代码的静态资源路径,不是打包后的静态资源路径,而第二种配置方式是匹配的打包后的静态资源路径,这时候你上传图片就不能访问正常访问路径。

所以,你应该两个同时改,同时操作的是打包后的静态资源文件。

更新后的:

静态资源映射配置:

java 复制代码
//静态资源映射
@Configuration
public class FileUploadConfig implements WebMvcConfigurer {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/static/face_img/**")
                .addResourceLocations("classpath:/static/face_img/");
    }
}

文件读写操作:

java 复制代码
  // 拿到文件名
   String filename = System.currentTimeMillis() + "_" + file.getOriginalFilename();

  // 存放上传图片的文件夹
   File fileDir = UploadUtils.getImgDirFile();
 // 输出文件夹绝对路径  -- 这里的绝对路径是相当于当前项目的路径而不是"容器"路径
   //  System.out.println(fileDir.getAbsolutePath());

  try {
       System.out.println(fileDir.getAbsolutePath());
       System.out.println(File.separator);
       System.out.println(fileDir.getAbsolutePath() + File.separator + filename);
    // 构建真实的文件路径
       File newFile = new File(fileDir.getAbsolutePath() + File.separator + filename);
       System.out.println(newFile);
    // 上传图片到 -》 "绝对路径"
       file.transferTo(newFile);
       msg = "上传成功!";

        return "/static/face_img/"+filename;
       } catch (IOException  e) {
        e.printStackTrace();
      }

重要是这个

复制代码
//            String fileDirPath = new String("src/main/resources/" + IMG_PATH_PREFIX);
//            File fileDir = new File(fileDirPath);

要改成

复制代码
ClassPathResource classPathResource = new ClassPathResource(IMG_PATH_PREFIX);File fileDir = null;
fileDir = classPathResource.getFile();
java 复制代码
public class UploadUtils {
    // 项目根路径下的目录  -- SpringBoot static 目录相当于是根路径下(SpringBoot 默认)
      public final static String IMG_PATH_PREFIX = "static/face_img";

      public static File getImgDirFile(){

    // 构建上传文件的存放 "文件夹" 路径
//     String fileDirPath = new String("src/main/resources/" + IMG_PATH_PREFIX);
//     File fileDir = new File(fileDirPath);
      // 获取类路径下的资源
      ClassPathResource classPathResource = new ClassPathResource(IMG_PATH_PREFIX);
       // 获取资源文件夹路径
        File fileDir = null;
     try {
      fileDir = classPathResource.getFile();
 if (!fileDir.exists()) {
       // 递归生成文件夹
          fileDir.mkdirs();
        }
      } catch (IOException e) {
           // 处理异常
                e.printStackTrace();
      }
            return fileDir;
     }

}
相关推荐
Fleshy数模2 分钟前
从数据获取到突破限制:Python爬虫进阶实战全攻略
java·开发语言
像少年啦飞驰点、11 分钟前
零基础入门 Spring Boot:从“Hello World”到可上线的 Web 应用全闭环指南
java·spring boot·web开发·编程入门·后端开发
苍煜14 分钟前
万字详解Maven打包策略:从基础插件到多模块实战
java·maven
有来技术18 分钟前
Spring Boot 4 + Vue3 企业级多租户 SaaS:从共享 Schema 架构到商业化套餐设计
java·vue.js·spring boot·后端
东东51640 分钟前
xxx医患档案管理系统
java·spring boot·vue·毕业设计·智慧城市
东东5161 小时前
学院个人信息管理系统 (springboot+vue)
vue.js·spring boot·后端·个人开发·毕设
一个响当当的名号1 小时前
lectrue9 索引并发控制
java·开发语言·数据库
进阶小白猿2 小时前
Java技术八股学习Day30
java·开发语言·学习
三水不滴2 小时前
Redis缓存更新策略
数据库·经验分享·redis·笔记·后端·缓存
hhy_smile2 小时前
Class in Python
java·前端·python