摘要:对于通过去下载文件时跨域的问题有一个解决思路是自己写一个代理服务代理服务负责在服务端下载文件并配置好跨域相关的信息然后请求走代理服务进行下载。
0. 概述
文件下载是web应用中很常见的场景,在浏览器中下载文件, 最基本的方式就是——在页面内隐藏iframe, 然后将文件下载地址加载到iframe中, 从而触发浏览器的下载行为。 此外, html5引入a标签的download属性, 也是一种下载方式。
下载
下面针对下载地址的Response Header、浏览器兼容性, 以及一些特殊case, 做一些说明。
1. 怎样的文件url才能触发浏览器的下载行为?能触发浏览器下载的url有两类:
response header中指定了Content-Disposition为attachment,它表示让浏览器把响应体作为附件下载到本地 (一般Content-Disposition还会指定filename, 下载的文件默认就是filename指定的名字)
response header中指定了Content-Type 为 application/octet-stream(无类型) 或者 application/zip(下载zip包时)以及其它几个不常见类型 (其中还有浏览器差异),其中 application/octet-stream表示http response为二进制流(没指定明确的type), 需要下载到本地, 由系统决定或者用户手动指定打开方式。
关于application/octet-stream的情况, 补充几点
这种response, 由于没有明确的type, 如果作为文件下载的话, 下载下来的文件将没有文件名和拓展名(文件名直接取的url path的最后一坨)
如果不作为文件下载, 比如已知response body是一张图片, 可以通过img标签来显示图片
下载下来的内容, 只是缺少文件拓展名而已, 文件内容是完整的, 如果知道它实际的拓展名, 手动改了就能通过系统默认的程序打开, 不改拓展名的话也能通过指定应用程序的方式打开
关于response header的Content-Type, 补充几点
首先要明确, Content-Type只是HTTP协议的部分, 不影响response body自身
Content-Type影响的是response的接收方(一般是浏览器), 对于浏览器而言, 它影响的是浏览器对响应体的处理方式. 比如指定为application/zip, 浏览器就会用pdf阅读器打开.
Content-Type之于浏览器, 就好比文件扩展名之于操作系统, 影响的默认行为, 如果你指定了打开方式, 那么Content-Type就不起作用了. 比如, 你在服务端对图片地址设置Content-Type为application/zip,但你在浏览器使用img标签(相当于指定了打开方式)去加载, 照样能正常加载图片。
为什么上面说的「Content-Type」还有「文件拓展名」对于文件自身没有影响?
这里涉及到「文件格式协议」/「文件头」等内容, 待补充...
只要满足上述「触发浏览器自动下载」的url, 就能通过iframe的形式.
一般的用法是在html中隐藏iframe, 然后在业务代码中通过设置iframe的src来实现下载.
download兼容性
主流浏览器对于的特殊情况说明:
Safari只支持「能触发浏览器下载」的url
Firefox也只支持「能触发浏览器下载」的url, 此外还有一个需要注意的地方——点击a标签时, 会触发「浏览器离开当前页面」的行为, 解决这个问题的方式是「再搭配一个iframe, 将a标签的target指向这个iframe」,这样就不会有页面跳转了
Chrome对于「不能触发浏览器下载」的url, 也可以通过这种方式下载。
4. 用哪种方式对于下载来源完全由自己控制的业务场景(意味着Response Header是统一的), 推荐
浏览器兼容性好
如果跟「下载」操作一起还有一系列操作按钮, 可以统一代码结构. (不然的话就「下载」操作按钮是用的a标签, 其它按钮不是)
对于下载来源不受控制的场景, 则可选择的方式
在chrome下, 比iframe方式兼容的下载场景多
番外. 迫不得已, 花式的下载方式构想这样的场景, 对于Response Header中Content-Type为image/png的图片url,能怎样下载呢?(这里不考虑‘右键另存为’)
对于Chrome浏览器,使用的方式可以下载, 但其他浏览器怎么办呢?
如果要强行下载这张图片的话, 想了下, 也是有办法的
代码中构造xhr请求该图片地址, 以Blob的形式接收Response, 然后转换成DataURL, 将DataURL的头部设置为image/octet-stream, 然后就可通过以上
上面构造xhr请求的方式存在CORS问题, 如果不满足跨域条件, 简单点的替换方案是使用img标签加载图片,然后画到canvas上, 然后导出为DataURL, 后续同上...
一些备注下载文件时, 在浏览器devTools的Network面板无法查看下载请求的http相关信息, 如果你想观察上面提到的Response Header中相关的信息, 可通过shell指令curl对下载地址发送HEAD请求, 以查看Response Header.
关于各种case的验证, 可自己简单写一个http服务, 设置不同的Response Header, 然后打开浏览器验证。
对于通过xhr去下载文件时跨域的问题, 有一个解决思路是, 自己写一个代理服务, 代理服务负责在服务端下载文件, 并配置好跨域相关的信息, 然后xhr请求走代理服务进行下载。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/54402.html
摘要:对于通过去下载文件时跨域的问题有一个解决思路是自己写一个代理服务代理服务负责在服务端下载文件并配置好跨域相关的信息然后请求走代理服务进行下载。 0. 概述 文件下载是web应用中很常见的场景,在浏览器中下载文件, 最基本的方式就是——在页面内隐藏iframe, 然后将文件下载地址加载到iframe中, 从而触发浏览器的下载行为。 此外, html5引入a标签的download属性, ...
摘要:说明本文主要讲述了的文件系统的小,逻辑不复杂,主要就是把上的一个文件下载到本地,和下载到中。写驱动由于没有驱动,需要自定义下在中写上名为的驱动同时在注册下该就行。执行命令后,显示上文件从上下载到上的文件该逻辑简单,但很好玩。 说明:本文主要讲述了Laravel的文件系统Filesystem的小Demo,逻辑不复杂,主要就是把Dropbox上的一个文件下载到本地local,和下载到AWS...
摘要:分布式爬虫框架详解随着互联网技术的发展与应用的普及,网络作为信息的载体,已经成为社会大众参与社会生活的一种重要信息渠道。下载器中间件位于引擎和下载器之间的框架,主要是处理引擎与下载器之间的请求及响应。 scrapy-redis分布式爬虫框架详解 随着互联网技术的发展与应用的普及,网络作为信息的载体,已经成为社会大众参与社会生活的一种重要信息渠道。由于互联网是开放的,每个人都可以在网络上...
摘要:目标是探索是否能够加快页面首屏速度。实验组浏览器支持,本次时,进行初始化。从上面的直观对比可以看出,个指标,组的分位值都略微大于组的分位值,差距在几十毫秒左右。最终,我也没有采用来优化首屏速度。 写在前面 本文首发于公众号:符合预期的CoyPan 不久之前,我简单探索了service worker在一个活动运营页面中的应用,可以参考我之前的这篇文章: service worker轻度探...
阅读 2545·2021-11-22 12:01
阅读 1072·2021-11-15 11:37
阅读 3657·2021-09-22 14:59
阅读 1716·2021-09-04 16:45
阅读 1365·2021-09-03 10:30
阅读 988·2021-08-11 11:18
阅读 2430·2019-08-30 10:53
阅读 1995·2019-08-29 15:13