Contents

前端下载图片或者文件的方式

前端下载资源的方式

目前前端直接下载 web 服务器或者 CDN 静态资源的方式有两种,一个是利用 <a>标签,另一个通过 window.open() 函数。今天重点讲一下 <a> 标签。

<a>标签

标签就是 html 中的超链接标签,但是用过这个标签的同学应该都有这种印象,当超链接链接的内容是图片、视频或者 pdf 时,点击超链接往往会在浏览器的新标签页中打开对应的资源,而不是开始下载。但是其他像压缩包这样的资源,也就是浏览器没办法直接打开的资源则会直接开始下载。问题来了,怎么样让所有的文件都 默认下载而不是打开呢?

HTML5 给 <a> 标签增加了一个 download 属性,当 <a> 标签戴上了 download 属性时,点击超链接则会被浏览器解析为下载而不是打开。

下面我们实际操作一下

一个不带 download 属性的 <a> 标签案例:

https://cdn.jsdelivr.net/gh/BallerJay/oss_images@master/blog/2022/07/2022-07-08/image-20220708225511893.png

浏览器打开之后,点击下载图片查看效果。

https://cdn.jsdelivr.net/gh/BallerJay/oss_images@master/blog/2022/07/2022-07-08/image-20220708225543974.png

随后浏览器打开了图片,但是并没有下载。

https://cdn.jsdelivr.net/gh/BallerJay/oss_images@master/blog/2022/07/2022-07-08/image-20220708225620317.png

<a>标签添加 download 属性后,在试一次

https://cdn.jsdelivr.net/gh/BallerJay/oss_images@master/blog/2022/07/2022-07-08/image-20220708225645027.png

添加 download 属性后,再次点击

https://cdn.jsdelivr.net/gh/BallerJay/oss_images@master/blog/2022/07/2022-07-08/image-20220708225710338.png

可以看到我们的图片已经下载,达到了我们想要的效果。

我们把 <img><a> 标签的路径换成一张网络图片,而非本地的图片。

https://cdn.jsdelivr.net/gh/BallerJay/oss_images@master/blog/2022/07/2022-07-08/image-20220708225804111.png

点击下载图片,会发现并没有下载,而是在浏览器中打开了图片。

注意: 如果你的图片渲染不出来,请在标签内加入 <meta name="referrer" content="no-referrer">

我们开始分析没有下载的原因

很可能是浏览器的 同源策略 导致 download 属性失效造成的。同源策略是浏览器的一种安全策略,所谓的同源指的是 URL 地址里面的协议、域名和端口号均相同,如果一个站点开启了同源策略,也称为禁止跨域访问;这时,这个站点的资源自允许在该站点内部跳转和访问,不允许被第三方站点访问和跳转。我们这个案例中由于源 cnblogs 的服务器设置了禁止跨域,在我们这个场景下的表现就是不能在非 cnblogs 站点下直接下载 cnblogs 文件,所以这里 download 属性会失效,而失效之后做的仅仅是跳转功能。

https://cdn.jsdelivr.net/gh/BallerJay/oss_images@master/blog/2022/07/2022-07-08/image-20220708225831096.png

参考文章

解决方案

换个推流的方式,也就是用 js 将资源按照二进制流的方式读取,对二进制流生成一个 url,这个 url 是我们自己站点可访问的 url,没有禁止跨域的限制。把 url 绑定到 <a> 标签的 href 属性中,因为浏览器无法打开二进制流文件,所以对于这样的资源,浏览器将开始下载而不是在浏览器中的打开资源。

https://cdn.jsdelivr.net/gh/BallerJay/oss_images@master/blog/2022/07/2022-07-08/image-20220708225936656.png

提示

  1. 在浏览器渲染 html 时,点击下载图片后会提示跨域报错的问题,这个可以通过 传送门 暂时屏蔽掉这个问题。

https://cdn.jsdelivr.net/gh/BallerJay/oss_images@master/blog/2022/07/2022-07-08/image-20220708230030158.png

下面是一篇关于谷歌浏览器跨域问题的博客,有时间可以看看:传送门