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

}
相关推荐
曹牧14 分钟前
文档格式:OFD
java
豆角焖肉39 分钟前
Maven进阶与搭建私服
java·maven
大不点wow1 小时前
Java序列化与反序列化:让对象走出JVM
java·开发语言·jvm
止语Lab1 小时前
好的 DX 不等于少写代码——三种语言的摩擦力设计课
后端
吃饱了得干活1 小时前
别再手动解析 LLM 输出了!LangChain 四种结构化输出方案对比
后端·python·langchain
噢,我明白了1 小时前
Java中日期和字符串的处理
java·开发语言·日期
程序员天天困1 小时前
Arthas trace 命令怎么用?一行定位最慢那行代码
jvm·后端
Huiturn1 小时前
GPT 5.6 连续编码 10 小时,纯 Python 啃下 Word 二进制格式——doc2docx 实现拆解
后端
dkbnull1 小时前
Spring Boot请求处理组件对比详解
java·spring boot
jun_bai1 小时前
Orthanc服务器使用java上传dicom影像文件
java·运维·服务器