🚢🚢🚢 浏览器打开图片链接为什么有时候是预览有时候是下载

6,681

本文正在参加「金石计划 . 瓜分6万现金大奖」

前言

应该有些靓仔也遇到过,有些图片链接点开在浏览器能够直接预览,有些图片却只能够下载 基于这个问题,我们来研究一下看看为什么?

答案

还是老样子,文章前面先上答案,没空的靓仔可以不往下看
浏览器打开图片链接是直接预览还是下载取决于图片链接的响应头Content-Disposition的属性

Content-Disposition 为 inline 在浏览器打开直接预览
Content-Disposition 为 attachment 在浏览器打开直接下载

分析

首先对于图片链接,本质上就是一个静态资源get请求,既然是请求,那么浏览器会有不同的表现,那肯定就是因为请求的返回体、返回头有差异,让浏览器作出不同的表现

浏览器通过什么识别图片是直接打开,还是唤起下载?

  1. 首先我们先找到两个有差异的图片链接,(如果没有这种链接可以去下载熊猫演示使用的demo使用的静态资源服务,通过docker配置好了两个静态资源的服务),github地址

image.png

服务启动好了,这里的静态资源服务demo
http://localhost:7776/img.png 在浏览器打开能直接预览
http://localhost:7777/img.png 在浏览器打开只能下载

image.png

如果大家自己找到了这两种不同的链接就用自己找到的两个链接对应替换来去验证下面的分析就好了

  1. 前面分析了,图片链接,本质上就是一个静态资源get请求,那么我们是否可以通过postman这类工具分别去请求一下,去看看请求具体返回来的内容到底有什么差异 http://localhost:7777/img.png 返回的body image.png

http://localhost:7776/img.png 返回的body image.png

postman返回来的请求body是一样的,返回来的都是图片内容,既然body是一致的,那么我们就再来看看请求头

http://localhost:7777/img.png 响应头 image.png

http://localhost:7776/img.png 响应头 image.png

从返回体的header会发现里面是有个Content-Disposition响应头是有差异的

Content-Disposition 是什么?

Content-Disposition 属性是作为对浏览器对下载文件的一个标识字段 Content-Disposition属性有两种类型:inlineattachment

inline :   将文件内容直接显示在页面 
attachment:弹出对话框让用户下载      

如果Content-Disposition没有设置,则默认是inline效果

到了这里,其实我们已经知道为什么图片链接有些在浏览器是直接预览有些是只能下载了,浏览器无非就是通过这个响应头来识别的

总结

我们已经知道了浏览器是通过响应头Content-Disposition,来标识到底是直接预览还是下载的,那么在开发过程,如果想让一个图片在浏览器预览(或下载),那么只需要调整响应头Content-Disposition属性即可了

实际场景一

上面说到了,想让一个图片在浏览器预览(或下载),需要改Content-Disposition,但是很多情况下,静态资源的链接的服务的响应头不是我们能控制的,这个时候需要怎么处理呢?

如:阿里云的oss默认是下载的,除非绑定自定义域名,否则是改不了预览的。也就是默认添加了
Content-Disposition: attachment;...

解:
我们可以通过nginx反向代理阿里云的oss的地址,这样就可以在我们自己的nginx服务里面做处理了 nginx.conf 配置

add_header "Content-Disposition" "inline;filename=文件名.后缀";

如果遇到了报错Multiple Content-Disposition。 原因是因为阿里云oss已经配置了Content-Disposition响应头,这个时候需要先用 proxy_hide_header 隐藏掉原来的 Content-Dispostion ,再用 add_header 来添加新的。

proxy_hide_header "Content-Disposition";
add_header "Content-Disposition" "inline;filename=文件名.后缀";
proxy_pass http://这里是服务器地址:端口;

实际场景二

同一个静态资源服务,实际开发中可能会有不同的,在A页面访问图片链接,需要直接在浏览器打开,但是在B页面访问图片链接需要让浏览器直接下载 那么其实我们只需要跟后端或者运维的小哥约定一下规则 同一个图片链接,通过query参数来判断是否需要在浏览器上直接预览 如: 访问可以直接在浏览器阅览 http://localhost:7777/img.png?inline=true

访问可以直接在浏览器下载
http://localhost:7777/img.png?inline=false
http://localhost:7777/img.png

至于具体如何根据inline=true去如何处理返回不同的响应头,就是后端小哥和运维小哥的活了
一般会在nginx上做处理的,读取query参数(可通过lua拓展去读取),然后add_header响应头

附:

除了图片,PDF之类的文件也同理

本文正在参加「金石计划 . 瓜分6万现金大奖」