springboot-vue图片上传功能(资源映射到本地磁盘,重启项目无影响)
将图片下载到本地指定目录下,配置spring boot资源处理器,
图片上传问题
提到图片上传我首先想到的是:图片文件传到后端时,获取后端项目部署路径,然后在路径下创建目录并将图片放入其中(如下):
String path = request.getSession().getServletContext().getRealPath("/upload");
然后存入数据库和返回前端的url是如下形式:
String url="http://localhost:8080/blog/upload/"+newFileName;
上述这种方法是将图片文件存入后端项目的目录内,具体是在tomcat部署后端项目的目录下(作为新手我的springboot项目只会使用内嵌的tomcat,没有尝试过其他服务器),这个目录就和tomcat设置有关,很难自己定制化决定存到哪里,而且最重要的一点就是重启项目后图片全部消失了,因为tomcat每次部署都会把之前在此处已经部署的项目清理掉,再重新部署新项目。这样后端把数据库里的url返回前端,前端拿着url来请求资源,发现根本就没有想要的资源。
解决方法
后端controller:
@PostMapping("/uploadAvatar")
public AjaxResult uploadAvatar(@RequestParam("avatarFile") MultipartFile avatarFile) throws IOException {
String uploadPath = UploadFileUtils.uploadImage("D:/mySystem/uploadPath", avatarFile);
}
UploadFileUtils是我自己写的文件上传工具类,uploadImage方法里的逻辑就是把图片文件下来到D盘的mySystem/uploadPath目录下,下载后返回url:
public class UploadFileUtils {
public static final String IMAGE_PNG = "image/png";
public static final String IMAGE_JPG = "image/jpg";
public static final String IMAGE_JPEG = "image/jpeg";
public static final String IMAGE_BMP = "image/bmp";
public static final String IMAGE_GIF = "image/gif";
public static String uploadImage(String path, MultipartFile file) throws IOException {
File filePath = new File(path+"/avatar"); // 这里我又加了一层目录
if (!filePath.exists()){
filePath.mkdirs();
}
//获取文件后缀
String extension = getExtension(Objects.requireNonNull(file.getContentType()));
//设置新文件名
String newFileName=UUID.randomUUID().toString().replace("-","")+"."+extension;
File targetFile = new File(filePath, newFileName);
file.transferTo(targetFile);
return "/profile/avatar/"+newFileName;
}
public static String getExtension(String prefix)
{
switch (prefix)
{
case IMAGE_PNG:
return "png";
case IMAGE_JPG:
return "jpg";
case IMAGE_JPEG:
return "jpeg";
case IMAGE_BMP:
return "bmp";
case IMAGE_GIF:
return "gif";
default:
return "";
}
}
}
这里返回的url并不是以http开头的,而是这样的:
/profile/avatar/4b4019b69d1840a4989bc4c19ad431bf.jpeg
而实际在磁盘中的存储路径为D:/mySystem/uploadPath/avatar/4b4019b69d1840a4989bc4c19ad431bf.jpeg
,这两个路径中/avatar前边的部分是不同的,为什么要在url前边加个/profile稍后会解答。前端拿到url后基于前端项目配置有两种处理方法:
- 若前端配置了代理,则加上代理前缀(如/dev-api)后将此url放入img标签的src属性中,
<img src="/dev-api/profile/avatar/4b4019b69d1840a4989bc4c19ad431bf.jpeg"></img>
,当页面加载图片时会向http:/前端ip:前端port//dev-api/profile/avatar/4b4019b69d1840a4989bc4c19ad431bf.jpeg
发送请求,这个请求会被代理转发,向后端http:/后端ip:后端port/profile/avatar/4b4019b69d1840a4989bc4c19ad431bf.jpeg
发送请求。 - 若前端没有配置代理,则将url拼接上
http:/后端ip:后端port
放入img标签内,<img src="http:/后端ip:后端port/profile/avatar/4b4019b69d1840a4989bc4c19ad431bf.jpeg"></img>
这时图片加载会直接向后端发送请求
以上两种方法,不论怎么处理目的都是让图片加载时向后端发送请求,请求路径为http:/后端ip:后端port/profile/avatar/4b4019b69d1840a4989bc4c19ad431bf.jpeg
。
然后就需要配置本篇的主角,向springboot中添加资源处理器
@Configuration
public class ResourcesConfig implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry)
{
//本地文件上传路径
registry.addResourceHandler("/profile" + "/**")
.addResourceLocations("file:" + "D:/mySystem/uploadPath/");
}
}
配置了这个后,所有以profile为前缀(去掉ip和端口)的请求,后端服务器都会去到指定的D:/mySystem/uploadPath/磁盘目录下找资源,以上边的请求为例,把请求路径中的/profile替换为D:/mySystem/uploadPath,后端服务器就会拿到如下资源给前端D:/mySystem/uploadPath/avatar/4b4019b69d1840a4989bc4c19ad431bf.jpeg。
总结起来就是向请求路径中添加一个虚拟路径,比如这里的/profile,然后把这个虚拟路径配置到spring boot中,配置对应的磁盘路径
更多推荐
所有评论(0)