利用 Aliyun OSS Nginx proxy module 实现OSS 图片处理回写功能

来源:互联网 发布:碟中谍 知乎 编辑:程序博客网 时间:2024/05/21 10:15

1、主要介绍内容

此篇文章主要利用Aliyun OSS Nginx proxy module 实现OSS 图片处理回写功能,借助OSS Nginx Proxy module 及 OSS 的上传回调功能实现OSS图片处理回写功能,当然文章目的并不在于强调图片处理回写功能,而是借实现一个例子来利用Aliyun OSS Nginx proxy module,对Nginx 及 Nginx lua 感兴趣的同学可以参照本文描述做出更强大的应用出来,本文如能抛砖引玉的作用那就不枉我花时间写此博客了。

2、开始之前

1、开始之前请稍微阅读下对Aliyun OSS Nginx proxy module 的简单介绍

http://blog.csdn.net/sunrain_chy/article/details/50935681

2、了解下阿里云OSS 上传回调功能

https://help.aliyun.com/document_detail/oss/api-reference/object/Callback.html?spm=5176.docoss/user_guide/manage_object/list_object.6.238.SAPehH

3、参考文章

在开始之前建议阅读本文之前建议阅读以上两篇参考文档
春哥的Nginx教程,会对Nginx 配置文件有很深的理解
http://openresty.org/download/agentzh-nginx-tutorials-zhcn.html
我的另外一篇博客,会更加理解OSS 提供的服务
http://blog.csdn.net/sunrain_chy/article/details/50804410

3、主要功能及优势

本文主要实现的功能是处理回写,这里以oss图片处理回写为例介绍如何利用阿里云OSS 提供的callback来进行图片回写。现在很多大图片如果每次都要实时处理那会大大降低用户体验(当然可以利用CDN进行缓存),那么可以通过此方法进行处理图回写,每次进行上传请求时带上callback参数让oss通知到本文中实现的nginx服务器,nginx服务器会自动从oss 拉取经过处理的数据然后再回写带oss中,如果确认成功甚至可以将原图删掉只保留处理图,这些都可以依据上传逻辑进行实现。那么肯定会有读者问那费用呢?这个完全不是问题,因为oss按照请求次数收费相当便宜几乎不要钱,而流量费用也不用担心,买一台和OSS同区域的ECS就可以走内网了,内网流量免费。

4、图片处理回写处理逻辑代码

oss_rewrite.lua

local cjson = require("cjson")local function get_object_data_from_oss_img(src_object, src_style)    local res = ngx.location.capture("/" .. src_object .. src_style)    if res.status ~= ngx.HTTP_OK then        ngx.log(ngx.ERR, "fetch external url data failed, object :", src_object .. src_style, " status:", tostring(res.status))        return res.status, nil    end    return res.status, res.bodyendlocal function get_and_process(json_table)    src_object = json_table["src_object"]    src_style = json_table["style"]    dst_object = json_table["dst_object"]    ngx.log(ngx.INFO, "src_object:", src_object, " style:", src_style, " dst_object:", dst_object)    if src_object == nil or src_style == nil or dst_object == nil then        ngx.log(ngx.ERR, "src_object style and dst_object should be not null")        return ngx.HTTP_BAD_REQUEST    end    -- Get processed img data from oss    local status, write_back_body = get_object_data_from_oss_img(src_object, src_style)    if status ~= ngx.HTTP_OK then        return status    end    -- Write back    local res = ngx.location.capture("/" .. dst_object, {        method = ngx.HTTP_PUT,        body = write_back_body    })    if res.status ~= ngx.HTTP_OK then        ngx.log(ngx.ERR, "write back to oss failed, object:", dst_object, "status:", tostring(res.status))        return res.status    end    return ngx.HTTP_OKendlocal function parse_and_process_post_body()    ngx.req.read_body()    local post_json_body = ngx.req.get_body_data()    ngx.log(ngx.INFO, post_json_body)    if post_json_body == nil then        ngx.log(ngx.ERR, "post request body from oss call_back is empty.")        return ngx.HTTP_BAD_REQUEST    end    -- decode json string and catch json errors    local succ, json_table = pcall(function()        return cjson.decode(post_json_body)    end)    if succ then        return get_and_process(json_table)    else        ngx.log(ngx.ERR, "post request body from oss call_back is not json.")        return ngx.HTTP_BAD_REQUEST    endendlocal method = ngx.req.get_method()if method == 'GET' or method == "POST" then    local status = parse_and_process_post_body()    if status == ngx.HTTP_OK then        ngx.say("{\"success\": \"true\"}")    else        ngx.log(ngx.ERR, "fail write back to oss")        ngx.exit(status)    endelse    ngx.log(ngx.INFO, "do not support this method ", method)    ngx.exit(ngx.HTTP_BAD_REQUEST)end

nginx.conf

error_log  logs/error.log  debug;events {    worker_connections  1024;}http {    include       mime.types;    lua_package_path "/usr/servers/lualib/?.lua;";    lua_package_cpath "/usr/servers/lualib/?.so;";     server {        listen       80;        server_name  your-server-name; # 注意此项要和CallBack 参数中的Host 保持一致        resolver 8.8.8.8;        #lua_code_cache  off; # 加上此配置在每次修改lua 代码后无需reload nginx        location /oss_write_back {            content_by_lua_file conf/lua/oss_rewrite.lua;        }        location / {            internal;  #只允许内部跳转            set $oss_bucket "you-oss-bucket";            set $oss_auth_id "you-access-key-id";            set $oss_auth_key "you-access-key-secret";            rewrite_by_lua_file conf/lua/oss_auth.lua;        }        location @oss {            #eg: bucket-example.oss-cn-qingdao.aliyuncs.com            proxy_pass http://$oss_bucket.oss-location.aliyuncs.com;        }    }}

5、如何使用上述代码及构造OSS call_back 请求

1、准备环境配置文件

自己搭建openresty 环境或者直接pull docker 官方镜像源openresty镜像
将oss_rewrite.lua 放到conf/lua/oss_rewrite.lua 中
将http://blog.csdn.net/sunrain_chy/article/details/50935681 提到的oss_auth.lua 放到conf/lua/oss_auth.lua 中
配置好nginx.conf 文件,启动nginx

2、构造Callback 请求

为了演示方便将bucket 权限设置为public-read-write并利用http://blog.csdn.net/sunrain_chy/article/details/50804410这篇文章介绍的方法进行请求构造

构造PUT 请求 call back 参数
callback.txt

{    "callbackUrl":"your-call-back-url/oss_write_back",    "callbackHost":"your-call-back-host",    "callbackBody":"{            \"src_object\":\"your-src-object-name\",            \"style\":\"style\",            \"dst_object\": \"your-dst-object-name\"        }",        "callbackBodyType":"application/json"}

注意这里的your-call-back-host 要与nginx.conf 中的server_name 保持一致,回调url 的location 要是oss_write_back
src_object 为oss上存在的一张图片object,通常设置为此次PUT 请求上传的Object
style 为 oss 图片处理参数
dst_object 为处理图回写到OSS 的objectname
对上述callback.txt 进行base64编码

$ base64 callback.txt | tr -d '\n'

这里写图片描述

3、构造带CallBack参数的PUT 请求

PUT /test.jpg HTTP/1.1Host: bucket-example.oss-ch-qingdao.aliyuncs.comAccept-ncoding: identityContent-Length: 0x-oss-callback-var: eyJ4Om15X3ZhciI6ImZvci1jYWxsYmFjay10ZXN0In0=x-oss-callback: ewogICAgImNhbGxiYWNrVXJsIjoiMzAuOS4xNjkuNDIvb3NzX3dyaXRlX2JhY2siLAogICAgImNhbGxiYWNrSG9zdCI6IjMwLjkuMTY5LjQyIiwKICAgICJjYWxsYmFja0JvZHkiOiJ7CiAgICAgICAgICAgIFwic3JjX29iamVjdFwiOlwidGVzdC5qcGdcIiwKICAgICAgICAgICAgXCJzdHlsZVwiOlwiQDEwMHdfMTAwaFwiLAogICAgICAgICAgICBcImRzdF9vYmplY3RcIjogXCJ0ZXN0LmpwZ18xMDB4MTAwXCIKICAgICAgICB9IiwKICAgICAgICAiY2FsbGJhY2tCb2R5VHlwZSI6ImFwcGxpY2F0aW9uL2pzb24iCn0K

注意上述x-oss-callback 参数为callback.txt 的base64编码

4、利用nc 将带call back 参数的请求发往oss

这里写图片描述

5、结果检测

在上述参数配置无误的情况下bucket中会多出来一个名为your-dst-object-name的object,这个object正是由your-src-object-name 带上style 参数经过OSS图片处理过的object。

6、程序运行主线

1、用户发送带callback参数的PUT请求到OSS,OSS根据callback提供的参数会调用用户的应用服务器,也就是我们的nginx

2、nginx 接收到这个请求后解析body参数获取到 源object 处理参数及回写object名,这一步走的是nginx conf 中的 location /oss_write_back

3、Nginx 根据解析出来的post 参数发出一个内部跳转的子请求到 location / 去OSS取出处理参数为style 的处理图,当然取图请求会经过oss_auth.lua 走到location @oss进行签名

4、取出处理图后nginx lua 发出自请求将处理图数据回写到OSS至此回写完成。

0 0
原创粉丝点击