Spring Boot对接Vue实现文件下载时res.data为undefined问题求助
Spring Boot 对接 Vue 实现文件下载时 res.data 为 undefined 的原因及解决方案
常见原因
- 封装的request响应拦截器直接返回了res.data
这是最高频的问题:多数项目封装axios的request工具时,会在响应拦截器中直接返回res.data简化后续业务代码取值,此时接口请求返回的res已经是接口返回的原始数据,再调用res.data自然为undefined。
- 封装的request响应拦截器直接返回了res.data
- 请求路径不匹配
后端Controller接口路径为/download/{path},如果Controller类上没有添加@RequestMapping("/files")注解,前端请求/files/download/xxx会404,返回的错误响应内容转blob后为空,也可能出现res.data为空的情况。另外如果path是目录、fileName是独立文件名,拼接时遗漏斜杠也会导致路径错误。
- 请求路径不匹配
- 后端未读取到有效文件
后端代码中硬编码了Windows系统的反斜杠\\作为路径分隔符,部署到Linux/Mac系统时会路径错误导致找不到文件,返回空流,此时响应内容长度为0。
- 后端未读取到有效文件
- responseType配置未生效
如果axios版本较低或者配置拼写错误,responseType: 'blob'未生效,返回的是普通文本响应,也可能出现数据解析异常。
- responseType配置未生效
解决方案
- 先确认响应结构
先把前端的打印语句改为打印完整响应对象,确认返回数据的结构,兼容拦截器的处理逻辑:
handleDownload(path,fileName){ // 拼接路径时补充斜杠,避免路径错误 request.get('/files/download/'+path + '/' + fileName, {responseType: 'blob'}).then(res => { // 打印完整响应定位结构 console.log('完整响应:', res) // 兼容两种情况:拦截器返回了res.data / 未返回 const blobData = res instanceof Blob ? res : res.data fileDownload(blobData, fileName); }).catch((err)=>{ console.log('download error: ', err); } ) }
- 修正请求路径和后端路径兼容性
- 确认Controller类上是否添加了
@RequestMapping("/files"),和前端请求路径前缀保持一致 - 后端路径拼接改为使用系统兼容的分隔符,增加文件存在校验和文件名编码:
public ResponseEntity<InputStreamResource> downloadFile(String path) throws IOException { // 用File.separator兼容不同操作系统 String filePath = System.getProperty("user.dir") + File.separator + "files" + File.separator + path; File file = new File(filePath); // 提前校验文件是否存在 if (!file.exists() || file.isDirectory()) { return ResponseEntity.notFound().build(); } FileSystemResource resource = new FileSystemResource(file); HttpHeaders headers = new HttpHeaders(); headers.add("Cache-Control", "no-cache, no-store, must-revalidate"); // 文件名编码避免中文乱码 headers.add("Content-Disposition", String.format("attachment; filename=\"%s\"", URLEncoder.encode(resource.getFilename(), "UTF-8"))); headers.add("Pragma", "no-cache"); headers.add("Expires", "0"); return ResponseEntity .ok() .headers(headers) .contentLength(resource.contentLength()) .contentType(MediaType.APPLICATION_OCTET_STREAM) .body(new InputStreamResource(resource.getInputStream())); }
- 校验responseType配置
确认axios版本在0.16及以上,responseType拼写正确,没有写成小写的responsetype。
内容的提问来源于stack exchange,提问作者Dai
相关产品推荐
相关产品推荐

