-- ========================================= -- 文件上传接口 -- ========================================= local upload = require "resty.upload" local cjson = require "cjson.safe" ngx.header.content_type = "application/json; charset=utf-8" local upload_dir = "/opt/oss/upload/" local max_size = 20 * 1024 * 1024 -- 20MB -- 工具函数 local function now_ms() return tostring(math.floor(ngx.now() * 1000)) end local function get_ym() return os.date("%Y%m") end local function safe_suffix(name) -- 获取文件后缀,例如 .png return name:match("^.+(%..+)$") or "" end local form, err = upload:new(4096) if not form then ngx.say(cjson.encode({ code = 500, msg = "创建上传对象失败: " .. (err or ""), data = {} })) return end form:set_timeout(10000) local file, filename, filesize = nil, nil, 0 while true do local typ, res, err = form:read() if not typ then ngx.say(cjson.encode({ code = 500, msg = "读取上传内容失败: " .. (err or ""), data = {} })) return end if typ == "header" then local name, value = res[1], res[2] if name == "Content-Disposition" then local orig_name = value:match('filename="(.-)"') if orig_name then local suffix = safe_suffix(orig_name) local newname = get_ym() .. "_" .. now_ms() .. suffix local fullpath = upload_dir .. newname -- 判断文件是否存在 local f = io.open(fullpath, "r") if f then f:close() ngx.say(cjson.encode({code = 429, msg = "当前访问人数较多,请稍后重试", data = {}})) return end -- 打开文件写入 file, err = io.open(fullpath, "w+") if not file then ngx.say(cjson.encode({ code = 500, msg = "无法创建文件: " .. (err or ""), data = {} })) return end filename = newname end end elseif typ == "body" then if file then filesize = filesize + #res if filesize > max_size then file:close() os.remove(upload_dir .. filename) ngx.say(cjson.encode({ code = 413, msg = "文件过大(限制20MB)", data = {} })) return end file:write(res) end elseif typ == "part_end" then if file then file:close() file = nil end elseif typ == "eof" then break end end ngx.say(cjson.encode({ code = 200, msg = "上传成功", data = { filename = filename, url = "/oss/upload/" .. filename, size = filesize } }))