SpringBoot映射URL访问本地文件

SpringBoot映射URL访问本地文件

基本实现

实现WebMvcConfigurer 接口,重写addResourceHandlers方法即可实现。

参考代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class MyWebMvcConfig implements WebMvcConfigurer {

@Value("${accessFile.resourceHandler}")
private String resourceHandler;

@Value("${accessFile.accessFilePath}")
private String accessFilePath;

/**
* 配置静态资源映射
*
* @param registry
*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// 匹配到resourceHandler,将URL映射至accessFilePath(即本地文件夹)
// registry.addResourceHandler("/files/**").addResourceLocations("file:E:/files/");
registry.addResourceHandler(resourceHandler).addResourceLocations("file:///" + accessFilePath);
}
}

举例:
resourceHandler 配置为/files/**,accessFilePath配置为E:/files/。
那么页面请求 ip:端口/context-path/files/需要访问的文件,即可访问到本地磁盘E:/files/下面的同名文件。
特别注意:

  • accessFilePath必须以"/"结尾,否则映射不到。

中文资源名称无法访问,英文名正常

解决办法一:重写configurePathMatch方法,UrlPathHelper设置不decodeurl

1
2
3
4
5
6
7
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
UrlPathHelper urlPathHelper=new UrlPathHelper();
urlPathHelper.setUrlDecode(false);
urlPathHelper.setDefaultEncoding(StandardCharsets.UTF_8.name());
configurer.setUrlPathHelper(urlPathHelper);
}

解决办法二:增加配置文件

1
2
3
4
spring:
mvc:
pathmatch:
matching-strategy: ant-path-matcher

这个方案适用于SpringBoot 2.6.+,而公司项目用的版本是2.7.+,使用上面的方法并没有生效。

文件预览-解决方案

由于访问服务器文件的方式不安全,且现在中文文件访问报错解决不了,最终重新写了一个文件下载接口,前端根据返回的文件流进行预览展示。
参考代码如下:

1
2
3
4
5
@Operation(summary = "在线预览pdf")
@GetMapping("/onlinePreview")
public void onlinePreview(@Valid @NotEmpty(message = "id不能为空") String id, HttpServletResponse response) {
jxOrgFileRecordService.onlinePreview(id,response);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
@Override
public void onlinePreview(String id, HttpServletResponse response) {
// 1、查询数据是否存在
JxOrgFileRecordEntity dbFileRecordVo = jxOrgFileRecordMapper.selectById(id);
if(dbFileRecordVo == null){
throw new BusinessException("未查询到报告记录数据。");
}
// 2、拼接服务器文件全路径:wordPath+year+pdfName
String pdfName = dbFileRecordVo.getPdfPath().substring(dbFileRecordVo.getPdfPath().lastIndexOf("/")+1);
String fullPath = wordPath+File.separator+year+File.separator+pdfName;
// 3、服务器文件是否存在
File file = new File(fullPath);
if (!file.exists()) {
log.error("onlinePreview 文件全路径:{}",fullPath);
throw new BusinessException("文件:{}不存在。",pdfName);
}
// 4、返回文件流
// 直接在try()中创建流对象 会默认关闭
try( FileInputStream input = new FileInputStream(file)) {
byte[] data = new byte[input.available()];
while (input.read(data) > 0) {
}
response.getOutputStream().write(data);
} catch(Exception ex) {
log.error("onlinePreview pdf文件处理异常:",ex);
}
}