OpenResty保存上传文件并返回uuid

今天前端给我提了个测试环境用的语音静态服务器的需求:

  • mp3 文件的上传和下载
  • 上传成功后返回唯一的文件标识符 (文件 id )

上传和下载用 Nginx 都比较简单,问题是返回唯一的文件 id 这里。看来要想快速搞定,只能用上 OpenResty 了。

文件的上传有个 resty.upload 模块,网上也有大量的代码示例,我直接参考了这篇博客

uuid 的实现,使用了 resty.jit-uuid,这个模块并没有集成到 OpenResty 中,可以直接从 github 上下载 jit-uuid.lua 文件,放到 OpenResty 的安装目录下的 lualib/resty 目录里。

具体的业务脚本如下:

-- myupload.lua

local uuid = require "resty.jit-uuid"  
local upload = require "resty.upload"

local chunk_size = 4096  
local form, err = upload:new(chunk_size)  
if not form then  
    ngx.log(ngx.ERR, "failed to new upload: ", err)
    ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
end

form:set_timeout(1000)

local saveRootPath = "/data/web/upload/"

local UUID = uuid()  
local fileName = saveRootPath .. UUID .. ".mp3"

local fileToSave = io.open(fileName, "w+")  
if not fileToSave then  
    ngx.log(ngx.ERR, "failed to open ", fileName)
    ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
end

local ret_save = false

while true do  
    local typ, res, err = form:read()
    if not typ then
        ngx.say("failed to read: ", err)
        return
    end

    if typ == "body" then
        if fileToSave then
            fileToSave:write(res)
        end
    elseif typ == "part_end" then
        if fileToSave then
            fileToSave:close()
            fileToSave = nil
        end
        ret_save = true
    elseif typ == "eof" then
        break
    else
        ;
    end
end

if ret_save then  
    ngx.say(UUID)
end  

配置文件:

location /upload {  
    content_by_lua_file lua/myupload.lua;
}

location / {  
    limit_rate 300k;
    root /data/web;
    if ($request_uri ~* "^/download/([0-9a-z-]+\.mp3$)") {
        set $filename $1;
        rewrite ^ /upload/$filename break;
    }
}

完成!!

当然了,这只是简单的测试环境的配置,如果真的要线上使用,上传类型的语音服务,还是用第三方服务比较靠谱!