惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

H
Help Net Security
G
Google Developers Blog
aimingoo的专栏
aimingoo的专栏
博客园 - 聂微东
酷 壳 – CoolShell
酷 壳 – CoolShell
小众软件
小众软件
Stack Overflow Blog
Stack Overflow Blog
美团技术团队
博客园_首页
T
Tailwind CSS Blog
博客园 - 三生石上(FineUI控件)
B
Blog
D
DataBreaches.Net
腾讯CDC
C
Check Point Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
U
Unit 42
月光博客
月光博客
V
V2EX
Vercel News
Vercel News
T
The Blog of Author Tim Ferriss
The Cloudflare Blog
博客园 - 叶小钗
Y
Y Combinator Blog

Jiajun的技术笔记

你好,2026! TiDB 源码阅读(六):TiDB Coprocessor 源码解析 性能优化的核心思想 TiDB 源码阅读(五):索引 TiDB 源码阅读(四):AST、逻辑计划、物理计划 CockroachDB Serverless Architecture podman 无故退出 Cursor Control-L (CTRL-L) Keyboard Shortcuts in Terminal Replace docker with podman Using xmonad with xfce4 A RC script for freebsd frpc 自己动手写一个k8s controller AI 会取代你的(编程)岗位吗? 自建DERP服务器提升Tailscale连接速度(使用Nginx转发) 自动升级Docker容器 再读《程序员修炼之道-从小工到专家》 再读《软件随想录》/《黑客与画家》/《软技能》 HTTP 压力测试中的 Coordinated Omission 2的补码 编程语言中的 context 是什么? flutter macOS 构建出错 Flatpak 使用小记 Golang CAS 操作是怎么实现的 PostgreSQL 当MQ来使用 Clash 结合 工作VPN 的网络设计 使用 PostgreSQL 搭建 JuiceFS PostgreSQL 配置优化和日志分析 有GitHub Copilot?那就可以搭建你的ChatGPT4服务 窗口函数的使用(以PG为例) 读《为什么学生不喜欢上学》
让浏览器下载文件
Jiajun Huang · 2024-09-06 · via Jiajun的技术笔记

让浏览器下载文件

不知道你是不是遇到过这样的需求,想要从服务器将一个文件发送给用户。原来我以为,直接遵循这么几步就可以:

  • 将文件内容写入到响应体中
  • 设置响应头中的 Content-Typeapplication/octet-stream
  • 设置响应头中的 Content-Dispositionattachment; filename=xxx

搞定,从后端来说,的确是这样就可以。

但是真正使用的时候,不一定能触发下载。因为浏览器是否会自动触发文件下载,有多种因素影响:

  • Content-Disposition 头,服务端需要设置为 attachment,这样浏览器才会提示下载
  • 浏览器本身的设置,如果设置了不自动下载,那么即使服务端设置了 attachment,也不会自动下载
  • 如果前端代码是通过AJAX请求的,那么即使服务端设置了 attachment,也不会自动下载,必须要在前端代码中做特殊处理
  • 如果服务器防火墙对下载做了限制,可能会被阻止下载

不过最常见的因素,是第一点和第三点。第一点是服务端设置不对,第三点是前端代码没有处理好。

前端的处理

写前端代码之前,我是不知道前端还需要做特殊处理的。我以为只要服务端设置了 attachment,浏览器就会自动下载。 不过实际上并非如此。

前端需要做如下处理:

$http.get('/download')
    .then(function (response) {
        var retData = response.data;

        const blob = new Blob([retData], {type: 'application/octet-stream'});
        const url = window.URL.createObjectURL(blob);
        const a = document.createElement('a');
        a.href = url;
        a.download = 'audit_log.csv';
        a.click();
    });

这里的关键点是:

  • 将返回的二进制数据转换为 Blob 对象
  • 通过 URL.createObjectURL 创建一个 URL
  • 创建一个 a 标签,设置 href 为上面创建的 URL,设置 download 为文件名
  • 触发 a.click() 事件

这样就可以触发下载了。

什么是Blob对象?Blob对象表示一个不可变、原始数据的类文件对象。Blob表示的数据不一定是一个JavaScript原生格式。 File接口基于Blob,继承了blob的功能并将其扩展使其支持用户系统上的文件。

总结

多学点前端知识,对后端开发也是有好处的。以前我就是纯粹的后端开发,对前端的知识了解的不多,以为只要服务端设置了对应的 头部,服务器就可以自动控制下载。实际上也不是这么简单的。


相关文章