springboot项目中javaweb上传了图片或文件,但是图片文件无法访问,出现404页面,甚至出现报错
这篇真的是笔者花了两个小时总结的经验,都快想吐槽谁写的史山代码[其实一年前自己写的],今天就奇了怪了,因为我想在不同环境或者主机的时候不用手动重写自己的绝对映射路径,也能正常运行静态资源访问的操作。但是但是!springboot项目中上传了图片,但是图片无法访问,出现404页面,甚至出现报错。
如果你静态资源映射配置这部分正确,图片文件读写也正确,那你就要考虑组合的问题了,这里不考虑图片文件读写的路径错误,统一用/static/face_img/加文件名的字符串
这是以前敲的:
静态资源映射配置(系统文件绝对路径):
//静态资源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\"); } }
文件读写操作:
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中。这种方式的好处是你的应用可以在不同环境中移植而不用担心资源路径的问题,但是缺点是你不能直接在文件系统中管理这些资源,需要通过重新打包应用来更新资源。
我想让我的应用可以在不同环境中移植而不用担心资源路径的问题,所以想改成第二种配置方式。
但是,文件读写也要同步改,因为原先写入的图片路径是源代码的静态资源路径,不是打包后的静态资源路径,而第二种配置方式是匹配的打包后的静态资源路径,这时候你上传图片就不能访问正常访问路径。
所以,你应该两个同时改,同时操作的是打包后的静态资源文件。
更新后的:
静态资源映射配置:
//静态资源映射 @Configuration public class FileUploadConfig implements WebMvcConfigurer { @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/static/face_img/**") .addResourceLocations("classpath:/static/face_img/"); } }
文件读写操作:
// 拿到文件名 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();
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; } }
还没有评论,来说两句吧...