目录
技术点
openResty
OpenResty® 是一个基于 Nginx 与 Lua 的高性能 Web 平台,其内部集成了大量精良的 Lua 库、第三方模块以及大多数的依赖项。用于方便地搭建能够处理超高并发、扩展性极高的动态 Web 应用、Web 服务和动态网关。
下载安装
请参考官网
示例
需要OpenResty 第三方模块,将第三方模块 拷贝到 lualib/resty 目录
- resty.http https://github.com.cnpmjs.org/ledgetech/lua-resty-http.git
- resty.oss https://github.com/362228416/lua-resty-oss.git
oss.lua 文件
--
-- Aliyun oss lua sdk
-- User: LinChao
-- Date: 2017/4/18
-- Time: 下午 5:24
local http = require "resty.http"
local _M = {
__version = "0.01"
}
local mt = {__index = _M}
function new(oss_config)
return setmetatable(oss_config, mt)
end
function put_object(self, content, content_type, object_name)
local headers, err = self:_build_auth_headers('PUT', content, content_type, object_name)
local url = "http://" .. headers['Host'] .. '/' .. object_name
local url_s = "https://" .. headers['Host'] .. '/' .. object_name
if err then return nil, err end
local res, err = self:_send_http_request(url, "PUT", headers, content)
if not res then
err = err or ''
return err
end
return url_s, object_name, res.body
end
function delete_object(self, object_name)
local headers, err = self:_build_auth_headers('DELETE', nil, nil, object_name)
local url = "http://" .. headers['Host'] .. '/' .. object_name
if err then return nil, err end
local res, err = self:_send_http_request(url, "DELETE", headers)
if 204 ~= res.status then
ngx.log(ngx.ERR, res.body, err)
return false, res.status
end
return true
end
function put_bucket(self, bucket)
self.bucket = bucket
local headers, err = self:_build_auth_headers('PUT')
local url = "http://" .. headers['Host'] .. '/'
if err then return nil, err end
local res, err = self:_send_http_request(url, "PUT", headers)
if not res then
return false, err
end
return true, nil, res.body
end
function put_bucket_acl(self, bucket, acl)
local current_bucket = self.bucket
self.bucket = bucket
local headers, err = self:_build_auth_headers('PUT', '', '', '', acl)
self.bucket = current_bucket
local url = "http://" .. headers['Host'] .. '/'
if err then return nil, err end
local res, err = self:_send_http_request(url, "PUT", headers)
if not res then
return false, err
end
return true, nil, res.body
end
function delete_bucket(self, bucket)
local current_bucket = self.bucket
self.bucket = bucket
local headers, err = self:_build_auth_headers('DELETE')
self.bucket = current_bucket
local url = "http://" .. headers['Host'] .. '/'
if err then return nil, err end
local res, err = self:_send_http_request(url, "DELETE", headers)
if not res then
return false, err
end
return true, nil, res.body
end
function _sign(self, str)
local key = ngx.encode_base64(ngx.hmac_sha1(self.secretKey, str))
return 'OSS '.. self.accessKey .. ':' .. key
end
function _send_http_request(self, url, method, headers, body)
local httpc = http.new()
httpc:set_timeout(30000)
local res, err = httpc:request_uri(url, {
method = method,
headers = headers,
body = body
})
httpc:set_keepalive(30000, 10)
return res, err
end
function _build_auth_headers(self, verb, content, content_type, object_name, acl)
local bucket = self.bucket
local endpoint = self.endpoint
local bucket_host = bucket .. "." .. endpoint
local Date = ngx.http_time(ngx.time())
local acl = acl or 'public-read'
local aclName = "x-oss-acl"
local MD5 = ngx.encode_base64(ngx.md5_bin(content))
local _content_type = content_type or "application/octet-stream"
local amz = "\n" .. aclName .. ":" ..acl
local resource = '/' .. bucket .. '/' .. (object_name or '')
local CL = string.char(10)
local check_param = verb .. CL .. MD5 .. CL .. _content_type .. CL .. Date .. amz .. CL .. resource
local headers = {
['Date'] = Date,
['Content-MD5'] = MD5,
['Content-Type'] = _content_type,
['Authorization'] = self:_sign(check_param),
['Connection'] = 'keep-alive',
['Host'] = bucket_host
}
headers[aclName] = acl
return headers
end
-- public
_M.new = new
_M.put_object = put_object
_M.delete_object = delete_object
_M.put_bucket = put_bucket
_M.put_bucket_acl = put_bucket_acl
_M.delete_bucket = delete_bucket
-- private
_M._build_auth_headers = _build_auth_headers
_M._send_http_request = _send_http_request
_M._sign = _sign
return _M
测试代码 text.lua
local upload = require "resty.upload"
local oss = require "resty.oss"
local http = require "resty.http"
-- 获取上传的文件
function readFile()
local chunk_size = 4096
local form, err = upload:new(chunk_size)
-- form:set_timeout(20000)
local file = {}
if not err then
while true do
local typ, res, err2 = form:read()
if not typ then
err = err2
print("failed to read: ", err2)
break
end
if typ == 'header' and res[1] == 'Content-Disposition' then
local filename = string.match(res[2], 'filename="(.*)"')
file.name = filename
end
if typ == 'header' and res[1] == 'Content-Type' then
file['type'] = res[2]
end
if typ == 'body' and file then
file[typ] = (file[typ] or '') .. res
end
if typ == "eof" then
break
end
end
end
return file, err
end
-- 根据文件类型判断 上传到那个bucket
function ulpoadBucket(file_type)
local type=''
if string.find(file_type,'video',1) then
type ='campusvideo'
elseif string.find(file_type,'audio',1) then
type='campusrecord'
elseif string.find(file_type,'image',1) then
type='campusfile'
else
type='campus002'
end
return type
end
--生成UUId
function guid()
local seed={'e','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'}
local tb={}
for i=1,32 do
table.insert(tb,seed[math.random(1,16)])
end
local sid=table.concat(tb)
return string.format('%s-%s-%s-%s-%s',
string.sub(sid,1,8),
string.sub(sid,9,12),
string.sub(sid,13,16),
string.sub(sid,17,20),
string.sub(sid,21,32)
)
end
local file, err = readFile()
if err then
ngx.say('{"status":-1,"msg":"上传失败"}')
else
local oss_config ={
accessKey='xxxxx',
secretKey='xxxx',
bucket='xxx',
endpoint='oss-cn-beijing.aliyuncs.com'
}
local type = ulpoadBucket(file.type)
oss_config['bucket']=type
local client = oss.new(oss_config)
local stuff = file.name:match(".+%.(%w+)$")
local file_name = guid() .. '.' .. stuff
local url = client:put_object(file.body,file.type,file_name)
ngx.say('{"status":0,"msg":"'..url..'"}')
end
nginx 配置
#user nobody;
worker_processes 1;
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/nginx.pid;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
#log_format main '$remote_addr - $remote_user [$time_local] "$request" '
# '$status $body_bytes_sent "$http_referer" '
# '"$http_user_agent" "$http_x_forwarded_for"';
#access_log logs/access.log main;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
#gzip on;
server {
listen 80;
server_name localhost;
resolver 8.8.8.8;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
root html;
index index.html index.htm;
}
location /hello {
client_body_buffer_size 20M;
client_max_body_size 50M;
default_type application/json;
content_by_lua_file lua/test.lua;
}
}
}