1、前言:
在做前后端分离项目,上传图片到服务器根路径下的文件夹里,若重启服务器,图片又无法访问,这是因为每次重启服务器之后,都会在
系统临时文件夹
内,创建一个新的服务器,图片就保存在这里,若重启,又会产生一个新的服务器,此时访问的就是新服务器的图片资源,而图片根本就不在新服务器内。
而且,系统的临时文件夹会
定期清理
,很有可能导致以前上传的文件丢失。
windows临时文件夹:
C:\Users\User\AppData\Local\Temp
/tmp
2、解决方案(4种):
(1)用图片服务器。。。。。。(我不会。。。)
(2)将SpringBoot项目打成war包
,放在Tomcat
容器中运行。
(3)修改SpringBoot内置tomcat的临时目录,这样临时目录的tomcat服务器就不会被清理了(不推荐
)
虽然不会被清理,但是我觉得,重启之后还是会创建新的tomcat,上传的图片又不见了。。。
而且,我这么配置了还是无效。
- 方法:在
application.yml
内,做如下设置
server:
port: 8080
tomcat:
basedir: E:/tomcat/temp #此位置可自己指定
(4)上传到指定文件夹,并配置资源映射(重点)
(推荐
)
3、正文
以方案(4)
为例,在windows
上进行
(1)在application.yml
文件中自定义图片保存位置
设置的图片保存路径的末尾必须有
/
,代码中默认保存路径最后已经带有/
了
Linux上的路径示例: /usr/developmentTool/myproject/bookstoreAPI/files/images/
Windows上的路径 示例: E:/images/
file-save-path: E:/images/
server:
port: 8080
tomcat:
uri-encoding: UTF-8
(2)Controller类
@RestController
@Slf4j
public class FileController {
/**
* 时间格式化
*/
private SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy/MM/dd/");
/**
* 图片保存路径,自动从yml文件中获取数据
* 示例: E:/images/
*/
@Value("${file-save-path}")
private String fileSavePath;
@GetMapping(path = "/upload")
public JsonResult uploadFile(MultipartFile file, HttpServletRequest request) {
//1.后半段目录: 2020/03/15
String directory = simpleDateFormat.format(new Date());
/**
* 2.文件保存目录 E:/images/2020/03/15/
* 如果目录不存在,则创建
*/
File dir = new File(fileSavePath + directory);
if (!dir.exists()) {
dir.mkdirs();
}
log.info("图片上传,保存位置:" + fileSavePath + directory);
//3.给文件重新设置一个名字
//后缀
String suffix = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));
String newFileName= UUID.randomUUID().toString().replaceAll("-", "")+suffix;
//4.创建这个新文件
File newFile = new File(fileSavePath + directory + newFileName);
//5.复制操作
try {
file.transferTo(newFile);
//协议 :// ip地址 :端口号 / 文件目录(/images/2020/03/15/xxx.jpg)
String url = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + "/images/" + directory + newFileName;
log.info("图片上传,访问URL:" + url);
return JsonResult.builder().data(url).message("上传成功!").code("1").build();
} catch (IOException e) {
return JsonResult.builder().data(null).message("IO异常!").code("-1").build();
}
}
}
上面的JsonResult
是我自己封装的一个类,用于响应给前端数据。
引入lombok依赖
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class JsonResult implements Serializable {
private String code;
private String message;
private Object data;
}
(2)配置资源映射(重点
)
@Configuration
public class WebConfig implements WebMvcConfigurer {
/**
* 图片保存路径,自动从yml文件中获取数据
* 示例: E:/images/
*/
@Value("${file-save-path}")
private String fileSavePath;
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
/**
* 配置资源映射
* 意思是:如果访问的资源路径是以“/images/”开头的,
* 就给我映射到本机的“E:/images/”这个文件夹内,去找你要的资源
* 注意:E:/images/ 后面的 “/”一定要带上
*/
registry.addResourceHandler("/images/**")
.addResourceLocations("file:"+fileSavePath);
}
}
(3)测试,上传一张图片
- 图片在本地保存成功
- 用返回的URL访问
http://localhost:8081/images/20200119104017_33650.jpg
重启100次服务器,图片照样都可以访问
附上原图,请笑纳: