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
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
|
|
|