Vue.js SSR场景下a标签download下载异常 获得HTML而非目标data.json文件
异常根因
你遇到的下载异常和a标签写法、download属性的拼写没有关系,核心原因是Vue SSR 架构下的静态资源托管规则配置缺失:
- 常规Web服务收到请求时,会优先匹配本地真实存在的静态文件,命中后直接返回对应文件的内容
- 绝大多数Vue SSR项目的服务端路由默认配了全路径兜底逻辑:所有没匹配到已定义页面路由的请求,会统一返回SSR应用的入口HTML文件
- 你点下载时请求的
/data.json路径没被服务端识别成静态文件,直接被兜底逻辑拦截返回了HTML源码,自然没法下到预期的{"key":"value"}JSON文件
可落地的解决方向
1. 修正SSR服务的静态资源托管逻辑(首选)
这是最稳妥、最符合SSR架构设计的解法,不需要改动你原来写的前端下载代码:
- 把
data.json文件移到项目约定的公共静态资源目录(比如Nuxt框架的public/、自研SSR项目的static/目录),别和页面业务源码混在一起 - 在SSR服务的所有业务路由规则之前,加上静态资源托管的中间件配置:要求服务收到请求时,优先匹配根路径下的静态文件,命中就直接返回对应文件,别再走后续的页面路由兜底逻辑
- 配置改完后,直接在浏览器地址栏访问
/data.json,如果能看到原始的JSON结构,就说明静态资源托管已经生效,你原来写的下载锚点代码可以直接正常用
2. 前端端内生成文件触发下载(快速替代方案)
如果暂时不方便调整服务端配置,可以绕开服务端路由拦截,直接在前端构造下载内容,完全躲开路由兜底的影响:
- 把需要导出的JSON内容直接内嵌到前端代码里,不需要单独发起对
/data.json的静态文件请求 - 用Blob对象构造JSON文件内容,生成临时下载地址绑定到a标签上:
// 构造对应JSON内容的Blob对象 const jsonContent = JSON.stringify({ key: 'value' }, null, 2) const jsonBlob = new Blob([jsonContent], { type: 'application/json' }) // 生成浏览器可识别的临时下载地址 const tempUrl = URL.createObjectURL(jsonBlob) // 绑定到下载锚点 const downloadLink = document.querySelector('a[download="data.json"]') downloadLink.href = tempUrl // 触发下载后释放临时内存,避免内存泄漏 downloadLink.addEventListener('click', () => { URL.revokeObjectURL(tempUrl) })
这种方案不需要依赖服务端的静态资源规则,哪怕服务端全路径返回HTML,也不会影响下载的文件内容,适合临时上线、或者需要动态生成JSON内容的需求。
3. 常见避坑点
- 别把JSON文件放到
src/assets这类会被构建工具处理的目录下:这类目录的文件在生产构建时会被webpack处理成带哈希的资源路径,根本没法通过/data.json的固定路径访问 - 生产环境部署时,要确认反向代理的规则优先级:如果反向代理把所有请求都转发给后端SSR服务,没有单独配置静态文件的匹配规则,哪怕开发环境下载功能正常,上线后还是会复现下载到HTML的问题
- 不需要纠结
download属性的跨域限制:只要最终返回的文件Content-Type是JSON类型,同域名下的download属性会正常触发保存文件逻辑,不会出现页面跳转
内容的提问来源于stack exchange,提问作者Pro Poop
相关产品推荐
相关产品推荐

