logo
发布于

使用lua上传文件到阿里云OSS

4613-–
作者
  • avatar
    姓名
    zhli

不知道为啥阿里云OSS官网竟然没有提供lua版本的API,Google了一下只有个在nginx环境使用的库: lua-resty-http。 于是造了个轮子,供参考。

  1. 安装luarocks
wget https://luarocks.org/releases/luarocks-3.8.0.tar.gz
tar zxpf luarocks-3.8.0.tar.gz
cd luarocks-3.8.0
./configure --with-lua-include=/usr/local/include --lua-version=5.2
  1. 安装库
luarocks install luasocket
luarocks install base64
luarocks install md5
luarocks install sha1
luarocks install mimetypes
  1. lua脚本
upload.lua
local http = require "socket.http"
local ltn12 = require "ltn12"
local base64 = require "base64"
local md5 = require "md5"
local sha1 = require "sha1"
local mimetypes = require 'mimetypes'

local filename = arg[1]

print("begin uploading file to ali oss: " .. filename .. "\n");

local oss_config = {                      
    accessKey	  =   "";
    secretKey	  =   "";
    bucket      =   "",
    endpoint    =   ""
}

function get_file_md5(filename)
    local file = io.open(filename,"rb")  

    if(file) then
        local string = file:read("*a")  
        file:close()

        return md5.sum(string)
    end

    return ''
end

function _sign(str)    
    local key = base64.encode(sha1.hmac_binary(oss_config.secretKey, str))
    return 'OSS ' .. oss_config.accessKey .. ':' .. key
end

function _build_auth_headers(verb, content, content_type, object_name)
    local bucket            =   oss_config.bucket
    local endpoint          =   oss_config.endpoint
    local bucket_host       =   bucket .. "." .. endpoint
    local Date              =   os.date("!%a, %d %b %Y %X GMT")        
    local MD5               =   base64.encode(get_file_md5(content))    
    local resource          =   '/' .. bucket .. '/' .. (object_name or '')
    local CL                =   "\n"    
    local check_param       =   verb .. CL .. MD5 .. CL .. content_type .. CL .. Date .. CL .. resource
    
    local headers  =	{
        ['Date']              =	Date,
        ['Content-MD5']		    =	MD5,
        ['Content-Type']	    =	content_type,
        ['Authorization']	    =	_sign(check_param),
        ['Connection']		    =	'keep-alive',
        ['Host']              =   bucket_host,
        ['Transfer-Encoding'] = 'chunked'
    }    
    
    return headers
end

function _send_http_request(url, method, headers, body)   
    local res_body = {} 
    local file = io.open(body,'rb')

    if(file) then
        local result, res_code = http.request{
            url = url,
            method = method,
            headers = headers,
            source = ltn12.source.file(io.open(body,'rb')),
            sink = ltn12.sink.table(res_body)
        }    

        file:close()

        if res_code == 200 then 
            return url
        end

        return nil,res_body[1]
    end

    return nil, "file not found"
end


function put_object(content, content_type, object_name)
    local headers, err  = _build_auth_headers('PUT', content, content_type, object_name)
    
    if err then return nil, err end
    
    local url = "http://" .. headers['Host'] .. '/' .. object_name

    return _send_http_request(url, "PUT", headers, content)
end

function get_file_name(file)
    return file:match("^.+/(.+)$")
end

local result,err = put_object(filename, mimetypes.guess(filename) or 'application/octet-stream', "fs_records/" .. get_file_name(filename))

if(err) then
    print("uploading record file failed. result: \n" .. err .. "\n")
else    
    print("uploading record file success. file url: " .. result .. "\n")
end
  1. 文件上传
lua upload.lua /var/temp.mp3