You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

140 lines
3.1 KiB
Lua

local upload = require("resty.upload")
local uuid = require("app.libs.uuid")
local sfind = string.find
local match = string.match
local ngx_var = ngx.var
local function getextension(filename)
return filename:match(".+%.(%w+)$")
end
local function _multipart_formdata(config)
local form, err = upload:new(config.chunk_size)
if not form then
ngx.log(ngx.ERR, "failed to new upload: ", err)
ngx.exit(500)
end
form:set_timeout(config.recieve_timeout)
local unique_name = uuid()
local success, msg = false, ""
local file, origin_filename, filename, path, extname, err
while true do
local typ, res, err = form:read()
if not typ then
success = false
msg = "failed to read"
ngx.log(ngx.ERR, "failed to read: ", err)
return success, msg
end
if typ == "header" then
if res[1] == "Content-Disposition" then
key = match(res[2], "name=\"(.-)\"")
origin_filename = match(res[2], "filename=\"(.-)\"")
elseif res[1] == "Content-Type" then
filetype = res[2]
end
if origin_filename and filetype then
if not extname then
extname = getextension(origin_filename)
end
if extname ~= "png" and extname ~= "jpg" and extname ~= "jpeg" and extname ~= "bmp" and extname ~= "gif" then
success = false
msg = "not allowed upload file type"
ngx.log(ngx.ERR, "not allowed upload file type:", origin_filename)
return success, msg
end
filename = unique_name .. "." .. extname
path = config.dir.. "/" .. filename
file, err = io.open(path, "w+")
if err then
success = false
msg = "open file error"
ngx.log(ngx.ERR, "open file error:", err)
return success, msg
end
end
elseif typ == "body" then
if file then
file:write(res)
success = true
else
success = false
msg = "upload file error"
ngx.log(ngx.ERR, "upload file error, path:", path)
return success, msg
end
elseif typ == "part_end" then
file:close()
file = nil
elseif typ == "eof" then
break
else
-- do nothing
end
end
return success, msg, origin_filename, extname, path, filename
end
local function uploader(config)
return function(req, res, next)
if ngx_var.request_method == "POST" then
local get_headers = ngx.req.get_headers()
local header = get_headers['Content-Type']
if header then
local is_multipart = sfind(header, "multipart")
if is_multipart and is_multipart>0 then
config = config or {}
config.dir = config.dir or "/tmp"
config.chunk_size = config.chunk_size or 4096
config.recieve_timeout = config.recieve_timeout or 20000 -- 20s
local success, msg, origin_filename, extname, path, filename = _multipart_formdata(config)
if success then
req.file = req.file or {}
req.file.success = true
req.file.origin_filename = origin_filename
req.file.extname = extname
req.file.path = path
req.file.filename = filename
else
req.file = req.file or {}
req.file.success = false
req.file.msg = msg
end
next()
else
next()
end
else
next()
end
else
next()
end
end
end
return uploader