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

}
相关推荐
也无晴也无风雨38 分钟前
深入剖析输入URL按下回车,浏览器做了什么
前端·后端·计算机网络
憨子周39 分钟前
2M的带宽怎么怎么设置tcp滑动窗口以及连接池
java·网络·网络协议·tcp/ip
霖雨2 小时前
使用Visual Studio Code 快速新建Net项目
java·ide·windows·vscode·编辑器
SRY122404192 小时前
javaSE面试题
java·开发语言·面试
Fiercezm3 小时前
JUC学习
java
无尽的大道3 小时前
Java 泛型详解:参数化类型的强大之处
java·开发语言
ZIM学编程3 小时前
Java基础Day-Sixteen
java·开发语言·windows
我不是星海3 小时前
1.集合体系补充(1)
java·数据结构
P.H. Infinity3 小时前
【RabbitMQ】07-业务幂等处理
java·rabbitmq·java-rabbitmq
爱吃土豆的程序员3 小时前
java XMLStreamConstants.CDATA 无法识别 <![CDATA[]]>
xml·java·cdata