阿里云OSS图片文件回源数量限制解决方案

阿里云OSS图片文件回源数量限制解决方案

背景

小程序在展示外链的源过多,而且地址不一定是https的,而小程序强制要求是https的,考虑使用OSS的回源功能,但是阿里的oss只能设置5个源。于是在中间加了一层将阿里云OSS 指向一台 ECS 的 Nginx 上做反向代理,配置如下:

server {
        listen       80 default_server;
        listen       [::]:80 default_server;
        server_name  localhost;
        
        # 不加上这句,部分域名会无法解析
        resolver 119.29.29.29 1.1.1.1;
        
        # 需要通过 –with-http_gunzip_module 参数启用
        # 加上这句如果图片被强制 gzip 压缩,nginx 会解压再返回解压后的内容,这样阿里云 OSS 不会报「图片格式不支持」的异常
        gunzip on;
        
        # 关闭 gzip 压缩
        gzip off;

        location / {
            # 直接取 「 ?」 后面部分当做图片原来的 url 去请求
            proxy_pass $args;
        }

访问地址格式如下

http://{bucket.domain}/{any_filename}.png?http://t07img.yangkeduo.com/images/2018-03-05/7263a4942abe93040c316e99b1044510.png

例子

http://xxxxx.oss-cn-hangzhou.aliyuncs.com/xxxxx.png?http://t07img.yangkeduo.com/images/2018-03-05/7263a4942abe93040c316e99b1044510.png

当我们访问阿里云OSS 的链接时,如果没有在 Bucket 中找到文件,阿里云OSS 会在配置好的回源地址中将除本域名以外的路径部分去访问回源域名,这里是我们的 Nginx 反向代理服务器[比如: 1.1.1.1],阿里云 OSS 会将地址转换为:

http://1.1.1.1/xxxxx.png?http://t07img.yangkeduo.com/images/2018-03-05/7263a4942abe93040c316e99b1044510.png

Nginx 按照配置会取 URL 的 GET 参数部分(或说是 query), 变量为 $args 部分去访问图片的源地址,于是就变成了

http://t07img.yangkeduo.com/images/2018-03-05/7263a4942abe93040c316e99b1044510.png

注意:按照常规GET本来 「 ?」 部分后面应该是 key1=value1&key2=value2 这样的形式,这里用法比较另类, url 其实相当于 key 部分,这样 url 被带过就可以直接让 nginx 在不需要进一步处理就直接反向代理,理论上可以代理任何域名下的图片地址。

将获取到的图片内容直接返回给 OSS,OSS 存储后再返回给客户端。整个过程都是同步的,如果服务器的带宽允许,延迟会比较小,而且在第二次请求时直接在 OSS 中读取。

这里遇到部分图片外链域名无法解析的情况需要加上

resolver 119.29.29.29 1.1.1.1;

如何在 OSS 回源时或回源后处理图片

因为已经带?了所以再使用 ?x-oss-process=style/stylename 就不合适了,如果放在 上一个 ? 之前会让 Nginx 报 404 因为变成了 ?x-oss-process=style/stylename?http://xxxx.com/img.png 很明显这不是一个 url 了,如果放在后面会当值图片处理参数失败。这时候就需要用到 OSS 的 「规则名称」 使用形如 !_w100 这样的完美解决。如此地址就变成了

http://{bucket.domain}/{any_filename}.png!_w100?http://t07img.yangkeduo.com/images/2018-03-05/7263a4942abe93040c316e99b1044510.png

回源时源地址开启了 Gzip 压缩导致图片存储无法处理

回源时图片加上图片处理参数会返回 ‘The Image Fomatter Is Not Supported’ 错误,但是查明阿里云明明是支持的这时就考虑是否是图片的编码出现了问题经过排查发现,我们拿浏览器去请求时 Request 头会带上 Accept-Encoding: gzip 字段,这是 Response 就会开启 Content-Encoding: gzip 此时的图片是被压缩过的,如果 Nginx 不做处理就会导致 OSS 存储下来的图片无法被处理

判断图片是否有压缩, 使用 python-magic 同时在 mac 上用安装 libmagic,这个库是用来看文件类型的。

# mac 需要安装支持库
brew install libmagic

# python 库
pip intall python-magic

import magic
magic.from_file('xxxxx.png')
# 'gzip compressed data, last modified: Wed Apr  3 11:34:22 2019, from Unix, original size 55202'

Linux 可以使用 file 来判断文件类型但是无法判断是否压缩文件

file 'xxx.png'

解决方法有二:

  • 在设置回源地址时禁止传递 Accept-Encoding 这样对方服务器可能就不启用压缩
  • 如果对方强制启用压缩,这时就需要在 Nginx 中启用 gunzip: on; 同时关闭 gzip: on;

参考

猜你喜欢

转载自www.cnblogs.com/dongyanglv/p/10908071.html