下载的几种方式
方案一:a 标签加 download 属性
这种情况下,必须保证 url 是处于同源的情况下,跨域时 download 属性是不生效的。download 属性指示浏览器该下载而不是打开该文件,同时该属性值即下载时的文件名;
例:
1 | <a href="url" download="filename"/> |
方案二:通过后端设置,设置下载的请求头为 Content-Disposition 使其强制让浏览器进行下载,这种方式不受跨域的影响 例:Content-Disposition: attachment; filename=”filename.jpg”
在常规的 HTTP 应答中,该响应头的值表示对响应内容的展现形式:
1.inline 表示将响应内容作为页面的一部分进行展示
2.attachment 表示将响应内容作为附件下载,大多数浏览器会呈现一个“保存为”的对话框
3.filename(可选) 指定为保存框中预填的文件名
这种情况下 使用 window.open()或者 a 标签不设置 download 属性都是可以让浏览器直接下载的
方案三:通过接口返回文件流的形式进行下载
当我们的请求已解决跨域的问题(如 nginx 或使用 axios 等),可以直接通过请求的方式拿到文件流,将文件流转为 blob 格式,再通过 a 标签的 download 属性下载。下面用 axios 进行举例
1 | // get请求 |
使用 xhr 也是可以的,例:
1 | const xhr = new XMLHttpRequest(); |
特别说明:
当用方案一二实现时,下载文件名优先取的是 Content-Disposition 的 filename 而不是 download,而通过 blob 的形式,文件名优先取的 download 属性,如果都没有设置则取的 url 最后一节;
当通过接口的形式访问文件,又想保留浏览器的预览效果时,可以仅设置 Content-Disposition 的 filename 以指定预览时下载的文件名,否则浏览器会默认取 url 最后一节,即 downloadfile 为文件名,导致下载的文件无后缀无法打开
window.open() 和 a 标签 执行的是打开链接的操作,类似于将地址直接输入到浏览器中,相当于从一个域跳到另一个域,因此 window.open(‘http://xxx')可以访问而不会报跨域错误;
浏览器取下载时文件名的优先级是 Content-Disposition: filename=“文件名.png” 优先于 优先于 url 最后一节 http://localhost:8087/upload/文件名.png
All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.
Comment


