后台给了个接口文档的 xml 地址,运维想让人下载留档,结果 Chrome 里点开直接渲染成树状结构,右键另存为还得选文件类型。用户以为没下载成功,反复点。

浏览器对 text/xml 和 application/xml 的默认行为是内联展示,除非服务端明确说这是附件。

服务端加一个响应头

Content-Disposition: attachment; filename=export.xml

有这一行,点击就是下载,不管浏览器能不能渲染。nginx 里在对应的 location 上加 add_header,Apache 用 Header set,后端接口则在输出前写 header。文件名带中文时补一个 filename 加星号的 UTF-8 编码版本,否则部分浏览器会存成乱码。

文件是动态生成的话,同时给 Content-Type: application/xml 和 Content-Length,下载进度才有得算,否则一直显示未知大小。

只有前端能改的情况

  • 同源地址,链接上加 download 属性,写上文件名,最简单。
  • 跨域地址,download 会被忽略,改用 fetch 拿 blob 再触发保存。
  • 内容是自己拼的字符串,先 new Blob 再 createObjectURL,用完记得 revoke。

还有一种情况是 xml 里声明了 UTF-8,实际却按别的编码保存,下载下来一打开全是问号。用编辑器另存为 UTF-8,并保证声明和实际一致,这两个地方经常对不上。

要不要顺手压缩

超过几兆的 xml 建议同时提供一份 zip。浏览器下载完 xml 再打开,很多工具会卡住几分钟,压缩包反而省事,传给别人也快。接口导出的数据尤其明显,动辄几十兆的节点树,压缩后往往只有十分之一。

微信和 QQ 的内置浏览器对这类下载支持有限,点了常提示不支持的文件类型,得让用户改用系统浏览器打开。给普通用户做的下载页,最好在按钮旁边写一句提示。按钮也别用脚本跳转,直接给正常的链接地址,被拦截时还有得兜底。