Fork me on Gitee

SpringMVC的@PathVariable中的特殊符号

下载文件中遇到的扩展名,即:@PathVariable中的特殊符号

背景

同事在开发业务功能时,遇到一个pdf下载的需求:列表查询返回数据后,点击【生成PDF】按钮,调用后台生成PDF的接口,上传到阿里云的OSS后,返回PDF的URL链接。
用户根据自身需要,觉得是否下载PDF文件。在和前端联调时,前端要求是下载并另存为的交互方式,而非在浏览器中预览。

根据自己之前在上传图片的经(cai)验(keng),为了解决IE浏览器下前端会下载后台返回的JSON,就将返回的对象改为String字符串,不同浏览器可以自动判断返回数据的content-type,并正常执行。
代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
/**
* 图片上传,返回String,优化IE浏览器提示下载json
*/
@ApiOperation(value = "阿里云OSS上传")
@PostMapping(value = "/aliyunOssUpload")
public String aliyunOssUpload(@RequestParam("file") MultipartFile uploadFile) {
...
Map<String,String> map = new HashMap<String,String>();
map.put("fileName", fileName);
map.put("fileUrl", fileUrl);
return JSON.toJSONString(CommonResult.success(map));
}

类似的问题,原因并不是相同,但万物之间都存在相互的关系,自己也想了解到原因,所以也加入了他们的讨论。
前端的要求很明确,但仔细分析下来发现,他要求的打开PDF链接后,是下载的文件的方式,但PDF链接是阿里云OSS的地址,不收后端控制。再借鉴
自己之前写的TestLink在线Excel用例转换xml 下载xml的代码,马上将找到的原因。
至少,我们需要将返回的PDF链接调整为自己服务的地址,前端请求PDF链接时,后端用流将数据写到前端。
问题明确后,代码很快就出来。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
   @ApiOperation("生成pdf")
@PostMapping(path = "/createPdf")
public CommonResult createPdf(@RequestBody @Valid PdfReq req)
MsCommonResult result= commonService.createPdf(req);
return result;
}

@ApiOperation("下载pdf")
@Authority(isSkip = true)
@GetMapping(path = "/downloadPdf/{fileName}")
public void downloadPdf(@PathVariable String fileName) {
// 这里是坑,被截掉了.pdf
if(!fileName.contains(".")) {
fileName = fileName + FileUtils.PDF_SUFFIX;
}
try (InputStream inputStream = ossClient.download("oss-bucket-pdf", fileName);){
HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
...
}
}

代码逻辑没有问题,但在downloadPdf方法中遇到接收的PathVariable参数fileName的扩展名没有了,前端传递的是20190712001.pdf,接受到的fileName却是20190712001。
为了实现功能,只好判断是否包含“.”,然后根据需要,拼接扩展名。

强大的SpringMVC竟然有这个坑,一定是自己没有抓到原因,必须研究学习下具体原因和原理。

分析

configurePathMatch(PathMatchConfigurer configurer)函数让开发人员可以根据需求定制URL路径的匹配规则。
configurer.setUseSuffixPatternMatch(false)表示设计人员希望系统对外暴露的URL不会识别和匹配.*后缀。

解决方案

使用Spel【墙裂推荐】

在@RequestMapping的value中使用SpEL来表示,value中的{version}换成{version:.+}或者{version:.*}

1
2
3
4
5
6
@GetMapping(path = "/downloadPdf/{fileName:.+}")
public void downloadPdf(@PathVariable String fileName) {

@GetMapping(path = "/downloadPdf/{fileName:.*}")
public void downloadPdf(@PathVariable String fileName) {
}

Spring web项目(未验证)

1
2
3
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">
<property name="useSuffixPatternMatch" value="false" />
</bean>

SpringBoot项目

在WebConfiguration类中添加对应的配置

1
2
3
4
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
configurer.setUseSuffixPatternMatch(false);
}

静态字符串

1
2
@GetMapping(path = "/downloadPdf/{fileName}/pdf")
public void downloadPdf(@PathVariable String fileName) {
感谢您发财的小手,我们一起进步
TEC-CHEN 微信支付

微信支付

TEC-CHEN 支付宝

支付宝

TEC-CHEN 微信-赞赏码

微信-赞赏码

TEC-CHEN 公众号

公众号


-------------本文结束感谢您的阅读-------------
0%